blob: 5310daa9df9fd76570be0de393ddadb660e1b303 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070030#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070032#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070033#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070034#include "llvm/ADT/DenseMap.h"
35#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070036using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070038using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070039
Chris Lattnerf7e22732018-06-22 22:03:48 -070040/// Simple enum to make code read better in cases that would otherwise return a
41/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070042enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattner48af7d12018-07-09 19:05:38 -070044namespace {
45class Parser;
46
47/// This class refers to all of the state maintained globally by the parser,
48/// such as the current lexer position etc. The Parser base class provides
49/// methods to access this.
50class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070051public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070052 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070053 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 : context(module->getContext()), module(module),
55 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070056 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
57 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070058
59 // A map from affine map identifier to AffineMap.
60 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070061
Uday Bondhugulabc535622018-08-07 14:24:38 -070062 // A map from integer set identifier to IntegerSet.
63 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070064
Chris Lattner4613d9e2018-08-19 21:17:22 -070065 // This keeps track of all forward references to functions along with the
66 // temporary function used to represent them and the location of the first
67 // reference.
68 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
69
Chris Lattnere79379a2018-06-22 10:39:19 -070070private:
Chris Lattner48af7d12018-07-09 19:05:38 -070071 ParserState(const ParserState &) = delete;
72 void operator=(const ParserState &) = delete;
73
74 friend class Parser;
75
76 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070077 MLIRContext *const context;
78
79 // This is the module we are parsing into.
80 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070081
82 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070083 Lexer lex;
84
85 // This is the next token that hasn't been consumed yet.
86 Token curToken;
87
Jacques Pienaar9c411be2018-06-24 19:17:35 -070088 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070089 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -070090
91 // The active OperationSet we're parsing with.
92 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070093};
94} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070095
Chris Lattner48af7d12018-07-09 19:05:38 -070096namespace {
97
Chris Lattner992a1272018-08-07 12:02:37 -070098typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070099 CreateOperationFunction;
100
Chris Lattner48af7d12018-07-09 19:05:38 -0700101/// This class implement support for parsing global entities like types and
102/// shared entities like SSA names. It is intended to be subclassed by
103/// specialized subparsers that include state, e.g. when a local symbol table.
104class Parser {
105public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700106 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700107
Chris Lattner2e595eb2018-07-10 10:08:27 -0700108 Parser(ParserState &state) : builder(state.context), state(state) {}
109
110 // Helper methods to get stuff from the parser-global state.
111 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700112 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700113 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700114 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700115 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700116
117 /// Return the current token the parser is inspecting.
118 const Token &getToken() const { return state.curToken; }
119 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700120
121 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700122 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700123 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700124 }
125 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700126
127 /// Advance the current lexer onto the next token.
128 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700129 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700130 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700131 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700132 }
133
134 /// Advance the current lexer onto the next token, asserting what the expected
135 /// current token is. This is preferred to the above method because it leads
136 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700137 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700138 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700139 consumeToken();
140 }
141
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700142 /// If the current token has the specified kind, consume it and return true.
143 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700144 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700145 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700146 return false;
147 consumeToken(kind);
148 return true;
149 }
150
Chris Lattnerf7702a62018-07-23 17:30:01 -0700151 /// Consume the specified token if present and return success. On failure,
152 /// output a diagnostic and return failure.
153 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
154
Chris Lattner40746442018-07-21 14:32:09 -0700155 /// Parse a comma-separated list of elements up until the specified end token.
156 ParseResult
157 parseCommaSeparatedListUntil(Token::Kind rightToken,
158 const std::function<ParseResult()> &parseElement,
159 bool allowEmptyList = true);
160
161 /// Parse a comma separated list of elements that must have at least one entry
162 /// in it.
163 ParseResult
164 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700165
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 // We have two forms of parsing methods - those that return a non-null
167 // pointer on success, and those that return a ParseResult to indicate whether
168 // they returned a failure. The second class fills in by-reference arguments
169 // as the results of their action.
170
Chris Lattnere79379a2018-06-22 10:39:19 -0700171 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700172 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700173 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700174 Type *parseTensorType();
175 Type *parseMemRefType();
176 Type *parseFunctionType();
177 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700178 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700179 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700180
Chris Lattner7121b802018-07-04 20:45:39 -0700181 // Attribute parsing.
182 Attribute *parseAttribute();
183 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
184
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700185 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700186 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700187 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700188 IntegerSet *parseIntegerSetInline();
189 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700190
Chris Lattner48af7d12018-07-09 19:05:38 -0700191private:
192 // The Parser is subclassed and reinstantiated. Do not add additional
193 // non-trivial state here, add it to the ParserState class.
194 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700195};
196} // end anonymous namespace
197
198//===----------------------------------------------------------------------===//
199// Helper methods.
200//===----------------------------------------------------------------------===//
201
Chris Lattner4c95a502018-06-23 16:03:42 -0700202ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700203 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700204 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700205 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700206 return ParseFailure;
207
Chris Lattner48af7d12018-07-09 19:05:38 -0700208 auto &sourceMgr = state.lex.getSourceMgr();
209 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700210 return ParseFailure;
211}
212
Chris Lattnerf7702a62018-07-23 17:30:01 -0700213/// Consume the specified token if present and return success. On failure,
214/// output a diagnostic and return failure.
215ParseResult Parser::parseToken(Token::Kind expectedToken,
216 const Twine &message) {
217 if (consumeIf(expectedToken))
218 return ParseSuccess;
219 return emitError(message);
220}
221
Chris Lattner40746442018-07-21 14:32:09 -0700222/// Parse a comma separated list of elements that must have at least one entry
223/// in it.
224ParseResult Parser::parseCommaSeparatedList(
225 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700226 // Non-empty case starts with an element.
227 if (parseElement())
228 return ParseFailure;
229
230 // Otherwise we have a list of comma separated elements.
231 while (consumeIf(Token::comma)) {
232 if (parseElement())
233 return ParseFailure;
234 }
Chris Lattner40746442018-07-21 14:32:09 -0700235 return ParseSuccess;
236}
237
238/// Parse a comma-separated list of elements, terminated with an arbitrary
239/// token. This allows empty lists if allowEmptyList is true.
240///
241/// abstract-list ::= rightToken // if allowEmptyList == true
242/// abstract-list ::= element (',' element)* rightToken
243///
244ParseResult Parser::parseCommaSeparatedListUntil(
245 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
246 bool allowEmptyList) {
247 // Handle the empty case.
248 if (getToken().is(rightToken)) {
249 if (!allowEmptyList)
250 return emitError("expected list element");
251 consumeToken(rightToken);
252 return ParseSuccess;
253 }
254
Chris Lattnerf7702a62018-07-23 17:30:01 -0700255 if (parseCommaSeparatedList(parseElement) ||
256 parseToken(rightToken, "expected ',' or '" +
257 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700258 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700259
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700260 return ParseSuccess;
261}
Chris Lattnere79379a2018-06-22 10:39:19 -0700262
263//===----------------------------------------------------------------------===//
264// Type Parsing
265//===----------------------------------------------------------------------===//
266
Chris Lattnerc3251192018-07-27 13:09:58 -0700267/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700268///
Chris Lattnerc3251192018-07-27 13:09:58 -0700269/// type ::= integer-type
270/// | float-type
271/// | other-type
272/// | vector-type
273/// | tensor-type
274/// | memref-type
275/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700276///
Chris Lattnerc3251192018-07-27 13:09:58 -0700277/// float-type ::= `f16` | `bf16` | `f32` | `f64`
278/// other-type ::= `affineint` | `tf_control`
279///
280Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700281 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700282 default:
283 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700284 case Token::kw_memref:
285 return parseMemRefType();
286 case Token::kw_tensor:
287 return parseTensorType();
288 case Token::kw_vector:
289 return parseVectorType();
290 case Token::l_paren:
291 return parseFunctionType();
292 // integer-type
293 case Token::inttype: {
294 auto width = getToken().getIntTypeBitwidth();
295 if (!width.hasValue())
296 return (emitError("invalid integer width"), nullptr);
297 consumeToken(Token::inttype);
298 return builder.getIntegerType(width.getValue());
299 }
300
301 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700302 case Token::kw_bf16:
303 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700304 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700305 case Token::kw_f16:
306 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700307 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700308 case Token::kw_f32:
309 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700310 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700311 case Token::kw_f64:
312 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700313 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700314
315 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700316 case Token::kw_affineint:
317 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700318 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700319 case Token::kw_tf_control:
320 consumeToken(Token::kw_tf_control);
321 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700322 case Token::kw_tf_string:
323 consumeToken(Token::kw_tf_string);
324 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700325 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700326}
327
328/// Parse a vector type.
329///
330/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
331/// const-dimension-list ::= (integer-literal `x`)+
332///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700333VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700334 consumeToken(Token::kw_vector);
335
Chris Lattnerf7702a62018-07-23 17:30:01 -0700336 if (parseToken(Token::less, "expected '<' in vector type"))
337 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338
Chris Lattner48af7d12018-07-09 19:05:38 -0700339 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700340 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700341
342 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700343 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700344 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700345 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700347 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348 dimensions.push_back(dimension.getValue());
349
350 consumeToken(Token::integer);
351
352 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700353 if (getToken().isNot(Token::bare_identifier) ||
354 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700355 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700356
357 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700358 if (getTokenSpelling().size() != 1)
359 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
361 // Consume the 'x'.
362 consumeToken(Token::bare_identifier);
363 }
364
365 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700366 auto typeLoc = getToken().getLoc();
367 auto *elementType = parseType();
368 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700369 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700370
Chris Lattnerc3251192018-07-27 13:09:58 -0700371 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
372 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700373
Chris Lattnerf7e22732018-06-22 22:03:48 -0700374 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700375}
376
377/// Parse a dimension list of a tensor or memref type. This populates the
378/// dimension list, returning -1 for the '?' dimensions.
379///
380/// dimension-list-ranked ::= (dimension `x`)*
381/// dimension ::= `?` | integer-literal
382///
383ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700384 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700385 if (consumeIf(Token::question)) {
386 dimensions.push_back(-1);
387 } else {
388 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700389 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700390 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
391 return emitError("invalid dimension");
392 dimensions.push_back((int)dimension.getValue());
393 consumeToken(Token::integer);
394 }
395
396 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700397 if (getToken().isNot(Token::bare_identifier) ||
398 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700399 return emitError("expected 'x' in dimension list");
400
401 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700402 if (getTokenSpelling().size() != 1)
403 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700404
405 // Consume the 'x'.
406 consumeToken(Token::bare_identifier);
407 }
408
409 return ParseSuccess;
410}
411
412/// Parse a tensor type.
413///
414/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
415/// dimension-list ::= dimension-list-ranked | `??`
416///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700417Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700418 consumeToken(Token::kw_tensor);
419
Chris Lattnerf7702a62018-07-23 17:30:01 -0700420 if (parseToken(Token::less, "expected '<' in tensor type"))
421 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422
423 bool isUnranked;
424 SmallVector<int, 4> dimensions;
425
426 if (consumeIf(Token::questionquestion)) {
427 isUnranked = true;
428 } else {
429 isUnranked = false;
430 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700431 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700432 }
433
434 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700435 auto typeLoc = getToken().getLoc();
436 auto *elementType = parseType();
437 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700438 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700439
Chris Lattnerc3251192018-07-27 13:09:58 -0700440 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
441 !isa<VectorType>(elementType))
442 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700443
MLIR Team355ec862018-06-23 18:09:09 -0700444 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700445 return builder.getTensorType(elementType);
446 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700447}
448
449/// Parse a memref type.
450///
451/// memref-type ::= `memref` `<` dimension-list-ranked element-type
452/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
453///
454/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
455/// memory-space ::= integer-literal /* | TODO: address-space-id */
456///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700457Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700458 consumeToken(Token::kw_memref);
459
Chris Lattnerf7702a62018-07-23 17:30:01 -0700460 if (parseToken(Token::less, "expected '<' in memref type"))
461 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700462
463 SmallVector<int, 4> dimensions;
464 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700465 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700466
467 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700468 auto typeLoc = getToken().getLoc();
469 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700470 if (!elementType)
471 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700472
Chris Lattnerc3251192018-07-27 13:09:58 -0700473 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
474 !isa<VectorType>(elementType))
475 return (emitError(typeLoc, "invalid memref element type"), nullptr);
476
MLIR Team718c82f2018-07-16 09:45:22 -0700477 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700478 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700479 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700480 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700481
MLIR Team718c82f2018-07-16 09:45:22 -0700482 auto parseElt = [&]() -> ParseResult {
483 if (getToken().is(Token::integer)) {
484 // Parse memory space.
485 if (parsedMemorySpace)
486 return emitError("multiple memory spaces specified in memref type");
487 auto v = getToken().getUnsignedIntegerValue();
488 if (!v.hasValue())
489 return emitError("invalid memory space in memref type");
490 memorySpace = v.getValue();
491 consumeToken(Token::integer);
492 parsedMemorySpace = true;
493 } else {
494 // Parse affine map.
495 if (parsedMemorySpace)
496 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700497 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700498 if (affineMap == nullptr)
499 return ParseFailure;
500 affineMapComposition.push_back(affineMap);
501 }
502 return ParseSuccess;
503 };
504
Chris Lattner413db6a2018-07-25 12:55:50 -0700505 // Parse a list of mappings and address space if present.
506 if (consumeIf(Token::comma)) {
507 // Parse comma separated list of affine maps, followed by memory space.
508 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
509 /*allowEmptyList=*/false)) {
510 return nullptr;
511 }
512 } else {
513 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
514 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700515 }
MLIR Team718c82f2018-07-16 09:45:22 -0700516
517 return MemRefType::get(dimensions, elementType, affineMapComposition,
518 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700519}
520
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700521/// Parse a function type.
522///
523/// function-type ::= type-list-parens `->` type-list
524///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700525Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700526 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700527
Chris Lattnerf7702a62018-07-23 17:30:01 -0700528 SmallVector<Type *, 4> arguments, results;
529 if (parseTypeList(arguments) ||
530 parseToken(Token::arrow, "expected '->' in function type") ||
531 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700532 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700533
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700534 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700535}
536
Chris Lattner1604e472018-07-23 08:42:19 -0700537/// Parse a list of types without an enclosing parenthesis. The list must have
538/// at least one member.
539///
540/// type-list-no-parens ::= type (`,` type)*
541///
542ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
543 auto parseElt = [&]() -> ParseResult {
544 auto elt = parseType();
545 elements.push_back(elt);
546 return elt ? ParseSuccess : ParseFailure;
547 };
548
549 return parseCommaSeparatedList(parseElt);
550}
551
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700552/// Parse a "type list", which is a singular type, or a parenthesized list of
553/// types.
554///
555/// type-list ::= type-list-parens | type
556/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700557/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700558///
James Molloy0ff71542018-07-23 16:56:32 -0700559ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700560 auto parseElt = [&]() -> ParseResult {
561 auto elt = parseType();
562 elements.push_back(elt);
563 return elt ? ParseSuccess : ParseFailure;
564 };
565
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700566 // If there is no parens, then it must be a singular type.
567 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700568 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700569
Chris Lattner40746442018-07-21 14:32:09 -0700570 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700571 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700572
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700573 return ParseSuccess;
574}
575
Chris Lattner4c95a502018-06-23 16:03:42 -0700576//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700577// Attribute parsing.
578//===----------------------------------------------------------------------===//
579
Chris Lattner7121b802018-07-04 20:45:39 -0700580/// Attribute parsing.
581///
582/// attribute-value ::= bool-literal
583/// | integer-literal
584/// | float-literal
585/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700586/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700587/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700588/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700589///
590Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700591 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700592 case Token::kw_true:
593 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700594 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700595 case Token::kw_false:
596 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700597 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700598
Jacques Pienaar84491092018-07-31 17:15:15 -0700599 case Token::floatliteral: {
600 auto val = getToken().getFloatingPointValue();
601 if (!val.hasValue())
602 return (emitError("floating point value too large for attribute"),
603 nullptr);
604 consumeToken(Token::floatliteral);
605 return builder.getFloatAttr(val.getValue());
606 }
Chris Lattner7121b802018-07-04 20:45:39 -0700607 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700608 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700609 if (!val.hasValue() || (int64_t)val.getValue() < 0)
610 return (emitError("integer too large for attribute"), nullptr);
611 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700612 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700613 }
614
615 case Token::minus: {
616 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700617 if (getToken().is(Token::integer)) {
618 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700619 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
620 return (emitError("integer too large for attribute"), nullptr);
621 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700622 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700623 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700624 if (getToken().is(Token::floatliteral)) {
625 auto val = getToken().getFloatingPointValue();
626 if (!val.hasValue())
627 return (emitError("floating point value too large for attribute"),
628 nullptr);
629 consumeToken(Token::floatliteral);
630 return builder.getFloatAttr(-val.getValue());
631 }
Chris Lattner7121b802018-07-04 20:45:39 -0700632
633 return (emitError("expected constant integer or floating point value"),
634 nullptr);
635 }
636
637 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700638 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700639 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700640 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700641 }
642
Chris Lattner85ee1512018-07-25 11:15:20 -0700643 case Token::l_square: {
644 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700645 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700646
647 auto parseElt = [&]() -> ParseResult {
648 elements.push_back(parseAttribute());
649 return elements.back() ? ParseSuccess : ParseFailure;
650 };
651
Chris Lattner85ee1512018-07-25 11:15:20 -0700652 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700653 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700654 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700655 }
James Molloyf0d2f442018-08-03 01:54:46 -0700656 case Token::hash_identifier:
657 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700658 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700659 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700660 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700661 return (emitError("expected constant attribute value"), nullptr);
662 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700663
664 case Token::at_identifier: {
665 auto nameLoc = getToken().getLoc();
666 Identifier name = builder.getIdentifier(getTokenSpelling().drop_front());
667 consumeToken(Token::at_identifier);
668
669 if (parseToken(Token::colon, "expected ':' and function type"))
670 return nullptr;
671 auto typeLoc = getToken().getLoc();
672 Type *type = parseType();
673 if (!type)
674 return nullptr;
675 auto fnType = dyn_cast<FunctionType>(type);
676 if (!fnType)
677 return (emitError(typeLoc, "expected function type"), nullptr);
678
679 // See if the function has already been defined in the module.
680 Function *function = getModule()->getNamedFunction(name);
681
682 // If not, get or create a forward reference to one.
683 if (!function) {
684 auto &entry = state.functionForwardRefs[name];
685 if (!entry.first) {
686 entry.first = new ExtFunction(name, fnType);
687 entry.second = nameLoc;
688 }
689 function = entry.first;
690 }
691
692 if (function->getType() != type)
693 return (emitError(typeLoc, "reference to function with mismatched type"),
694 nullptr);
695
696 return builder.getFunctionAttr(function);
697 }
698
James Molloyf0d2f442018-08-03 01:54:46 -0700699 default: {
700 if (Type *type = parseType())
701 return builder.getTypeAttr(type);
702 return nullptr;
703 }
704 }
Chris Lattner7121b802018-07-04 20:45:39 -0700705}
706
Chris Lattner7121b802018-07-04 20:45:39 -0700707/// Attribute dictionary.
708///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700709/// attribute-dict ::= `{` `}`
710/// | `{` attribute-entry (`,` attribute-entry)* `}`
711/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700712///
James Molloy0ff71542018-07-23 16:56:32 -0700713ParseResult
714Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700715 consumeToken(Token::l_brace);
716
717 auto parseElt = [&]() -> ParseResult {
718 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700719 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
720 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700721 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700722 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700723 consumeToken();
724
Chris Lattnerf7702a62018-07-23 17:30:01 -0700725 if (parseToken(Token::colon, "expected ':' in attribute list"))
726 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700727
728 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700729 if (!attr)
730 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700731
732 attributes.push_back({nameId, attr});
733 return ParseSuccess;
734 };
735
Chris Lattner40746442018-07-21 14:32:09 -0700736 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700737 return ParseFailure;
738
739 return ParseSuccess;
740}
741
742//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700743// Polyhedral structures.
744//===----------------------------------------------------------------------===//
745
Chris Lattner2e595eb2018-07-10 10:08:27 -0700746/// Lower precedence ops (all at the same precedence level). LNoOp is false in
747/// the boolean sense.
748enum AffineLowPrecOp {
749 /// Null value.
750 LNoOp,
751 Add,
752 Sub
753};
MLIR Teamf85a6262018-06-27 11:03:08 -0700754
Chris Lattner2e595eb2018-07-10 10:08:27 -0700755/// Higher precedence ops - all at the same precedence level. HNoOp is false in
756/// the boolean sense.
757enum AffineHighPrecOp {
758 /// Null value.
759 HNoOp,
760 Mul,
761 FloorDiv,
762 CeilDiv,
763 Mod
764};
Chris Lattner7121b802018-07-04 20:45:39 -0700765
Chris Lattner2e595eb2018-07-10 10:08:27 -0700766namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700767/// This is a specialized parser for affine structures (affine maps, affine
768/// expressions, and integer sets), maintaining the state transient to their
769/// bodies.
770class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700771public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700772 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700773
Chris Lattner2e595eb2018-07-10 10:08:27 -0700774 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700775 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700776
Chris Lattner2e595eb2018-07-10 10:08:27 -0700777private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700778 // Binary affine op parsing.
779 AffineLowPrecOp consumeIfLowPrecOp();
780 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700781
Chris Lattner2e595eb2018-07-10 10:08:27 -0700782 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700783 ParseResult parseDimIdList(unsigned &numDims);
784 ParseResult parseSymbolIdList(unsigned &numSymbols);
785 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700786
787 AffineExpr *parseAffineExpr();
788 AffineExpr *parseParentheticalExpr();
789 AffineExpr *parseNegateExpression(AffineExpr *lhs);
790 AffineExpr *parseIntegerExpr();
791 AffineExpr *parseBareIdExpr();
792
793 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700794 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700795 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
796 AffineExpr *rhs);
797 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
798 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
799 AffineLowPrecOp llhsOp);
800 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700801 AffineHighPrecOp llhsOp,
802 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700803 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700804
805private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700806 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700807};
808} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700809
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700810/// Create an affine binary high precedence op expression (mul's, div's, mod).
811/// opLoc is the location of the op token to be used to report errors
812/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700813AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
814 AffineExpr *lhs,
815 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700816 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700817 switch (op) {
818 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700819 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700820 emitError(opLoc, "non-affine expression: at least one of the multiply "
821 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700822 return nullptr;
823 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700824 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700825 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700826 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700827 emitError(opLoc, "non-affine expression: right operand of floordiv "
828 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700829 return nullptr;
830 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700831 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700832 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700833 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700834 emitError(opLoc, "non-affine expression: right operand of ceildiv "
835 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700836 return nullptr;
837 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700838 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700839 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700840 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700841 emitError(opLoc, "non-affine expression: right operand of mod "
842 "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.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700846 case HNoOp:
847 llvm_unreachable("can't create affine expression for null high prec op");
848 return nullptr;
849 }
850}
851
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700852/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700853AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
854 AffineExpr *lhs,
855 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700856 switch (op) {
857 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700858 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700859 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700860 return builder.getAddExpr(
861 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700862 case AffineLowPrecOp::LNoOp:
863 llvm_unreachable("can't create affine expression for null low prec op");
864 return nullptr;
865 }
866}
867
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700868/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700870AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700871 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700872 case Token::plus:
873 consumeToken(Token::plus);
874 return AffineLowPrecOp::Add;
875 case Token::minus:
876 consumeToken(Token::minus);
877 return AffineLowPrecOp::Sub;
878 default:
879 return AffineLowPrecOp::LNoOp;
880 }
881}
882
883/// Consume this token if it is a higher precedence affine op (there are only
884/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700885AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700886 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700887 case Token::star:
888 consumeToken(Token::star);
889 return Mul;
890 case Token::kw_floordiv:
891 consumeToken(Token::kw_floordiv);
892 return FloorDiv;
893 case Token::kw_ceildiv:
894 consumeToken(Token::kw_ceildiv);
895 return CeilDiv;
896 case Token::kw_mod:
897 consumeToken(Token::kw_mod);
898 return Mod;
899 default:
900 return HNoOp;
901 }
902}
903
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700904/// Parse a high precedence op expression list: mul, div, and mod are high
905/// precedence binary ops, i.e., parse a
906/// expr_1 op_1 expr_2 op_2 ... expr_n
907/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
908/// All affine binary ops are left associative.
909/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
910/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700911/// null. llhsOpLoc is the location of the llhsOp token that will be used to
912/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700913AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
914 AffineHighPrecOp llhsOp,
915 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700916 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700917 if (!lhs)
918 return nullptr;
919
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700920 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700921 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700922 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700923 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700924 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925 if (!expr)
926 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700927 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700928 }
929 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700930 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700931 }
932
933 // This is the last operand in this expression.
934 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700935 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700936
937 // No llhs, 'lhs' itself is the expression.
938 return lhs;
939}
940
941/// Parse an affine expression inside parentheses.
942///
943/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700944AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700945 if (parseToken(Token::l_paren, "expected '('"))
946 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700947 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700948 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700949
Chris Lattner2e595eb2018-07-10 10:08:27 -0700950 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700951 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700953 if (parseToken(Token::r_paren, "expected ')'"))
954 return nullptr;
955
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 return expr;
957}
958
959/// Parse the negation expression.
960///
961/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700962AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700963 if (parseToken(Token::minus, "expected '-'"))
964 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700965
Chris Lattner2e595eb2018-07-10 10:08:27 -0700966 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700967 // Since negation has the highest precedence of all ops (including high
968 // precedence ops) but lower than parentheses, we are only going to use
969 // parseAffineOperandExpr instead of parseAffineExpr here.
970 if (!operand)
971 // Extra error message although parseAffineOperandExpr would have
972 // complained. Leads to a better diagnostic.
973 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700974 auto *minusOne = builder.getConstantExpr(-1);
975 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976}
977
978/// Parse a bare id that may appear in an affine expression.
979///
980/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -0700981AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700982 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700983 return (emitError("expected bare identifier"), nullptr);
984
Chris Lattner48af7d12018-07-09 19:05:38 -0700985 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700986 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700987 if (entry.first == sRef) {
988 consumeToken(Token::bare_identifier);
989 return entry.second;
990 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700991 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700992
993 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700994}
995
996/// Parse a positive integral constant appearing in an affine expression.
997///
998/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -0700999AffineExpr *AffineParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001000 // No need to handle negative numbers separately here. They are naturally
1001 // handled via the unary negation operator, although (FIXME) MININT_64 still
1002 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -07001003 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001004 return (emitError("expected integer"), nullptr);
1005
Chris Lattner48af7d12018-07-09 19:05:38 -07001006 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001007 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
1008 return (emitError("constant too large for affineint"), nullptr);
1009 }
1010 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001011 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001012}
1013
1014/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001015/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1016/// operator, the rhs of which is being parsed. This is used to determine
1017/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001018// Eg: for an expression without parentheses (like i + j + k + l), each
1019// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1020// operand expression, it's an op expression and will be parsed via
1021// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1022// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001023AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001024 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001025 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001026 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001027 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001028 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001029 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001030 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001031 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001032 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001033 case Token::kw_ceildiv:
1034 case Token::kw_floordiv:
1035 case Token::kw_mod:
1036 case Token::plus:
1037 case Token::star:
1038 if (lhs)
1039 emitError("missing right operand of binary operator");
1040 else
1041 emitError("missing left operand of binary operator");
1042 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001043 default:
1044 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001045 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001046 else
1047 emitError("expected affine expression");
1048 return nullptr;
1049 }
1050}
1051
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001052/// Parse affine expressions that are bare-id's, integer constants,
1053/// parenthetical affine expressions, and affine op expressions that are a
1054/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001055///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001056/// All binary op's associate from left to right.
1057///
1058/// {add, sub} have lower precedence than {mul, div, and mod}.
1059///
Uday Bondhugula76345202018-07-09 13:47:52 -07001060/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1061/// ceildiv, and mod are at the same higher precedence level. Negation has
1062/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001063///
1064/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001065/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1066/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1067/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001068/// associativity.
1069///
1070/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001071/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1072/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001073AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1074 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001075 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001076 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001077 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001078
1079 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001080 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001081 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001082 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001083 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084 }
1085 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001086 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001087 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001088 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001089 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001090 // We have a higher precedence op here. Get the rhs operand for the llhs
1091 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001092 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001093 if (!highRes)
1094 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001096 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001097 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001098 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001099 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001100
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001101 // Recurse for subsequent low prec op's after the affine high prec op
1102 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001103 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1104 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001105 return expr;
1106 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001107 // Last operand in the expression list.
1108 if (llhs)
1109 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1110 // No llhs, 'lhs' itself is the expression.
1111 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001112}
1113
1114/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001115/// affine-expr ::= `(` affine-expr `)`
1116/// | `-` affine-expr
1117/// | affine-expr `+` affine-expr
1118/// | affine-expr `-` affine-expr
1119/// | affine-expr `*` affine-expr
1120/// | affine-expr `floordiv` affine-expr
1121/// | affine-expr `ceildiv` affine-expr
1122/// | affine-expr `mod` affine-expr
1123/// | bare-id
1124/// | integer-literal
1125///
1126/// Additional conditions are checked depending on the production. For eg., one
1127/// of the operands for `*` has to be either constant/symbolic; the second
1128/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001129AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001130 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001131}
1132
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001133/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001134/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001135/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001136ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001137 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001138 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001139
1140 auto name = getTokenSpelling();
1141 for (auto entry : dimsAndSymbols) {
1142 if (entry.first == name)
1143 return emitError("redefinition of identifier '" + Twine(name) + "'");
1144 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001145 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001146
1147 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001148 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001149}
1150
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001151/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001152ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001153 consumeToken(Token::l_square);
1154 auto parseElt = [&]() -> ParseResult {
1155 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1156 return parseIdentifierDefinition(symbol);
1157 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001158 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001159}
1160
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001161/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001162ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001163 if (parseToken(Token::l_paren,
1164 "expected '(' at start of dimensional identifiers list"))
1165 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001166
Chris Lattner413db6a2018-07-25 12:55:50 -07001167 auto parseElt = [&]() -> ParseResult {
1168 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1169 return parseIdentifierDefinition(dimension);
1170 };
Chris Lattner40746442018-07-21 14:32:09 -07001171 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001172}
1173
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001174/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001175///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001176/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1177/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1178/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001179///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001180/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001181AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001182 unsigned numDims = 0, numSymbols = 0;
1183
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001184 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001185 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001186 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001187
1188 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001189 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001190 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001191 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001192 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001193
1194 if (parseToken(Token::arrow, "expected '->' or '['") ||
1195 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001196 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001197
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001198 SmallVector<AffineExpr *, 4> exprs;
1199 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001200 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001201 ParseResult res = elt ? ParseSuccess : ParseFailure;
1202 exprs.push_back(elt);
1203 return res;
1204 };
1205
1206 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001207 // affine expressions); the list cannot be empty.
1208 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001209 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001210 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001211
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001212 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001213 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1214 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1215 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001216 // TODO: check if sizes are non-negative whenever they are constant.
1217 SmallVector<AffineExpr *, 4> rangeSizes;
1218 if (consumeIf(Token::kw_size)) {
1219 // Location of the l_paren token (if it exists) for error reporting later.
1220 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001221 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1222 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001223
1224 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001225 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001226 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001227 if (!elt)
1228 return ParseFailure;
1229
1230 if (!elt->isSymbolicOrConstant())
1231 return emitError(loc,
1232 "size expressions cannot refer to dimension values");
1233
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001234 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001235 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001236 };
1237
Chris Lattner40746442018-07-21 14:32:09 -07001238 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001239 return nullptr;
1240 if (exprs.size() > rangeSizes.size())
1241 return (emitError(loc, "fewer range sizes than range expressions"),
1242 nullptr);
1243 if (exprs.size() < rangeSizes.size())
1244 return (emitError(loc, "more range sizes than range expressions"),
1245 nullptr);
1246 }
1247
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001248 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001249 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001250}
1251
Chris Lattner2e595eb2018-07-10 10:08:27 -07001252AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001253 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001254}
1255
MLIR Team718c82f2018-07-16 09:45:22 -07001256AffineMap *Parser::parseAffineMapReference() {
1257 if (getToken().is(Token::hash_identifier)) {
1258 // Parse affine map identifier and verify that it exists.
1259 StringRef affineMapId = getTokenSpelling().drop_front();
1260 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1261 return (emitError("undefined affine map id '" + affineMapId + "'"),
1262 nullptr);
1263 consumeToken(Token::hash_identifier);
1264 return getState().affineMapDefinitions[affineMapId];
1265 }
1266 // Try to parse inline affine map.
1267 return parseAffineMapInline();
1268}
1269
MLIR Teamf85a6262018-06-27 11:03:08 -07001270//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001271// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001272//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001273
Chris Lattner7f9cc272018-07-19 08:35:28 -07001274namespace {
1275/// This class contains parser state that is common across CFG and ML functions,
1276/// notably for dealing with operations and SSA values.
1277class FunctionParser : public Parser {
1278public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001279 enum class Kind { CFGFunc, MLFunc };
1280
1281 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001282
Chris Lattner6119d382018-07-20 18:41:34 -07001283 /// After the function is finished parsing, this function checks to see if
1284 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001285 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001286
1287 /// This represents a use of an SSA value in the program. The first two
1288 /// entries in the tuple are the name and result number of a reference. The
1289 /// third is the location of the reference, which is used in case this ends up
1290 /// being a use of an undefined value.
1291 struct SSAUseInfo {
1292 StringRef name; // Value name, e.g. %42 or %abc
1293 unsigned number; // Number, specified with #12
1294 SMLoc loc; // Location of first definition or use.
1295 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001296
1297 /// Given a reference to an SSA value and its type, return a reference. This
1298 /// returns null on failure.
1299 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1300
1301 /// Register a definition of a value with the symbol table.
1302 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1303
1304 // SSA parsing productions.
1305 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001306 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001307
1308 template <typename ResultType>
1309 ResultType parseSSADefOrUseAndType(
1310 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1311
1312 SSAValue *parseSSAUseAndType() {
1313 return parseSSADefOrUseAndType<SSAValue *>(
1314 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1315 return resolveSSAUse(useInfo, type);
1316 });
1317 }
Chris Lattner40746442018-07-21 14:32:09 -07001318
1319 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001320 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001321 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1322 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001323
1324 // Operations
1325 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001326 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1327 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001328
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001329protected:
1330 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1331
Chris Lattner7f9cc272018-07-19 08:35:28 -07001332private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001333 /// Kind indicates if this is CFG or ML function parser.
1334 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001335 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001336 /// their name. This has one entry per result number.
1337 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1338
1339 /// These are all of the placeholders we've made along with the location of
1340 /// their first reference, to allow checking for use of undefined values.
1341 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1342
1343 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1344
1345 /// Return true if this is a forward reference.
1346 bool isForwardReferencePlaceholder(SSAValue *value) {
1347 return forwardReferencePlaceholders.count(value);
1348 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001349};
1350} // end anonymous namespace
1351
Chris Lattner6119d382018-07-20 18:41:34 -07001352/// Create and remember a new placeholder for a forward reference.
1353SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1354 Type *type) {
1355 // Forward references are always created as instructions, even in ML
1356 // functions, because we just need something with a def/use chain.
1357 //
1358 // We create these placeholders as having an empty name, which we know cannot
1359 // be created through normal user input, allowing us to distinguish them.
1360 auto name = Identifier::get("placeholder", getContext());
1361 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1362 getContext());
1363 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1364 return inst->getResult(0);
1365}
1366
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001367/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001368/// it specifies. This returns null on failure.
1369SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001370 auto &entries = values[useInfo.name];
1371
Chris Lattner7f9cc272018-07-19 08:35:28 -07001372 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001373 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1374 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001375 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001376 if (result->getType() == type)
1377 return result;
1378
Chris Lattner6119d382018-07-20 18:41:34 -07001379 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1380 "' expects different type than prior uses");
1381 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001382 return nullptr;
1383 }
1384
Chris Lattner6119d382018-07-20 18:41:34 -07001385 // Make sure we have enough slots for this.
1386 if (entries.size() <= useInfo.number)
1387 entries.resize(useInfo.number + 1);
1388
1389 // If the value has already been defined and this is an overly large result
1390 // number, diagnose that.
1391 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1392 return (emitError(useInfo.loc, "reference to invalid result number"),
1393 nullptr);
1394
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001395 // Otherwise, this is a forward reference. If we are in ML function return
1396 // an error. In CFG function, create a placeholder and remember
1397 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001398 if (getKind() == Kind::MLFunc)
1399 return (
1400 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1401 nullptr);
1402
Chris Lattner6119d382018-07-20 18:41:34 -07001403 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1404 entries[useInfo.number].first = result;
1405 entries[useInfo.number].second = useInfo.loc;
1406 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001407}
1408
1409/// Register a definition of a value with the symbol table.
1410ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001411 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001412
Chris Lattner6119d382018-07-20 18:41:34 -07001413 // Make sure there is a slot for this value.
1414 if (entries.size() <= useInfo.number)
1415 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001416
Chris Lattner6119d382018-07-20 18:41:34 -07001417 // If we already have an entry for this, check to see if it was a definition
1418 // or a forward reference.
1419 if (auto *existing = entries[useInfo.number].first) {
1420 if (!isForwardReferencePlaceholder(existing)) {
1421 emitError(useInfo.loc,
1422 "redefinition of SSA value '" + useInfo.name + "'");
1423 return emitError(entries[useInfo.number].second,
1424 "previously defined here");
1425 }
1426
1427 // If it was a forward reference, update everything that used it to use the
1428 // actual definition instead, delete the forward ref, and remove it from our
1429 // set of forward references we track.
1430 existing->replaceAllUsesWith(value);
1431 existing->getDefiningInst()->destroy();
1432 forwardReferencePlaceholders.erase(existing);
1433 }
1434
1435 entries[useInfo.number].first = value;
1436 entries[useInfo.number].second = useInfo.loc;
1437 return ParseSuccess;
1438}
1439
1440/// After the function is finished parsing, this function checks to see if
1441/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001442ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001443 // Check for any forward references that are left. If we find any, error out.
1444 if (!forwardReferencePlaceholders.empty()) {
1445 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1446 // Iteration over the map isn't determinstic, so sort by source location.
1447 for (auto entry : forwardReferencePlaceholders)
1448 errors.push_back({entry.second.getPointer(), entry.first});
1449 llvm::array_pod_sort(errors.begin(), errors.end());
1450
1451 for (auto entry : errors)
1452 emitError(SMLoc::getFromPointer(entry.first),
1453 "use of undeclared SSA value name");
1454 return ParseFailure;
1455 }
1456
Chris Lattner40746442018-07-21 14:32:09 -07001457 // Run the verifier on this function. If an error is detected, report it.
1458 std::string errorString;
1459 if (func->verify(&errorString))
1460 return emitError(loc, errorString);
1461
Chris Lattner6119d382018-07-20 18:41:34 -07001462 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001463}
1464
Chris Lattner78276e32018-07-07 15:48:26 -07001465/// Parse a SSA operand for an instruction or statement.
1466///
James Molloy61a656c2018-07-22 15:45:24 -07001467/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001468///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001469ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001470 result.name = getTokenSpelling();
1471 result.number = 0;
1472 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001473 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1474 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001475
1476 // If we have an affine map ID, it is a result number.
1477 if (getToken().is(Token::hash_identifier)) {
1478 if (auto value = getToken().getHashIdentifierNumber())
1479 result.number = value.getValue();
1480 else
1481 return emitError("invalid SSA value result number");
1482 consumeToken(Token::hash_identifier);
1483 }
1484
Chris Lattner7f9cc272018-07-19 08:35:28 -07001485 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001486}
1487
1488/// Parse a (possibly empty) list of SSA operands.
1489///
1490/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1491/// ssa-use-list-opt ::= ssa-use-list?
1492///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001493ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001494FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001495 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001496 return ParseSuccess;
1497 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001498 SSAUseInfo result;
1499 if (parseSSAUse(result))
1500 return ParseFailure;
1501 results.push_back(result);
1502 return ParseSuccess;
1503 });
Chris Lattner78276e32018-07-07 15:48:26 -07001504}
1505
1506/// Parse an SSA use with an associated type.
1507///
1508/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001509template <typename ResultType>
1510ResultType FunctionParser::parseSSADefOrUseAndType(
1511 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001512
Chris Lattnerf7702a62018-07-23 17:30:01 -07001513 SSAUseInfo useInfo;
1514 if (parseSSAUse(useInfo) ||
1515 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1516 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001517
Chris Lattner7f9cc272018-07-19 08:35:28 -07001518 auto *type = parseType();
1519 if (!type)
1520 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001521
James Molloy61a656c2018-07-22 15:45:24 -07001522 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001523}
1524
Chris Lattner2c402672018-07-23 11:56:17 -07001525/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1526/// followed by a type list. If hasParens is true, then the operands are
1527/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001528///
Chris Lattner2c402672018-07-23 11:56:17 -07001529/// ssa-use-and-type-list[parens]
1530/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1531///
1532/// ssa-use-and-type-list[!parens]
1533/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001534///
Chris Lattner40746442018-07-21 14:32:09 -07001535template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001536ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001537 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1538
1539 // If we are in the parenthesized form and no paren exists, then we succeed
1540 // with an empty list.
1541 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001542 return ParseSuccess;
1543
Chris Lattner2c402672018-07-23 11:56:17 -07001544 SmallVector<SSAUseInfo, 4> valueIDs;
1545 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001546 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001547
1548 if (isParenthesized && !consumeIf(Token::r_paren))
1549 return emitError("expected ')' in operand list");
1550
1551 // If there were no operands, then there is no colon or type lists.
1552 if (valueIDs.empty())
1553 return ParseSuccess;
1554
Chris Lattner2c402672018-07-23 11:56:17 -07001555 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001556 if (parseToken(Token::colon, "expected ':' in operand list") ||
1557 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001558 return ParseFailure;
1559
1560 if (valueIDs.size() != types.size())
1561 return emitError("expected " + Twine(valueIDs.size()) +
1562 " types to match operand list");
1563
1564 results.reserve(valueIDs.size());
1565 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1566 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1567 results.push_back(cast<ValueTy>(value));
1568 else
1569 return ParseFailure;
1570 }
1571
1572 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001573}
1574
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001575/// Parse the CFG or MLFunc operation.
1576///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001577/// operation ::=
1578/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1579/// `:` function-type
1580///
1581ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001582FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001583 auto loc = getToken().getLoc();
1584
1585 StringRef resultID;
1586 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001587 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001588 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001589 if (parseToken(Token::equal, "expected '=' after SSA name"))
1590 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001591 }
1592
Chris Lattner85ee1512018-07-25 11:15:20 -07001593 Operation *op;
1594 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1595 op = parseCustomOperation(createOpFunc);
1596 else if (getToken().is(Token::string))
1597 op = parseVerboseOperation(createOpFunc);
1598 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001599 return emitError("expected operation name in quotes");
1600
Chris Lattner85ee1512018-07-25 11:15:20 -07001601 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001602 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001603 return ParseFailure;
1604
Chris Lattnerf7bdf952018-08-05 21:12:29 -07001605 // Apply location information to the instruction.
1606 // TODO(clattner): make this more principled. We shouldn't overwrite existing
1607 // location info, we should use a better serialized form, and we shouldn't
1608 // be using the :location attribute. This is also pretty inefficient.
1609 {
1610 auto &sourceMgr = getSourceMgr();
1611 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
1612 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
1613 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
1614 op->setAttr(builder.getIdentifier(":location"),
1615 builder.getIntegerAttr(locationEncoding));
1616 }
1617
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001618 // We just parsed an operation. If it is a recognized one, verify that it
1619 // is structurally as we expect. If not, produce an error with a reasonable
1620 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001621 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001622 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001623 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001624 }
1625
Chris Lattner7f9cc272018-07-19 08:35:28 -07001626 // If the instruction had a name, register it.
1627 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001628 if (op->getNumResults() == 0)
1629 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001630
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001631 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001632 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1633 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001634 }
1635
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001636 return ParseSuccess;
1637}
Chris Lattnere79379a2018-06-22 10:39:19 -07001638
Chris Lattner85ee1512018-07-25 11:15:20 -07001639Operation *FunctionParser::parseVerboseOperation(
1640 const CreateOperationFunction &createOpFunc) {
1641 auto name = getToken().getStringValue();
1642 if (name.empty())
1643 return (emitError("empty operation name is invalid"), nullptr);
1644
1645 consumeToken(Token::string);
1646
Chris Lattner992a1272018-08-07 12:02:37 -07001647 OperationState result(builder.getIdentifier(name));
1648
Chris Lattner85ee1512018-07-25 11:15:20 -07001649 // Parse the operand list.
1650 SmallVector<SSAUseInfo, 8> operandInfos;
1651
1652 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1653 parseOptionalSSAUseList(operandInfos) ||
1654 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1655 return nullptr;
1656 }
1657
Chris Lattner85ee1512018-07-25 11:15:20 -07001658 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001659 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001660 return nullptr;
1661 }
1662
1663 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1664 return nullptr;
1665
1666 auto typeLoc = getToken().getLoc();
1667 auto type = parseType();
1668 if (!type)
1669 return nullptr;
1670 auto fnType = dyn_cast<FunctionType>(type);
1671 if (!fnType)
1672 return (emitError(typeLoc, "expected function type"), nullptr);
1673
Chris Lattner992a1272018-08-07 12:02:37 -07001674 result.types.append(fnType->getResults().begin(), fnType->getResults().end());
1675
Chris Lattner85ee1512018-07-25 11:15:20 -07001676 // Check that we have the right number of types for the operands.
1677 auto operandTypes = fnType->getInputs();
1678 if (operandTypes.size() != operandInfos.size()) {
1679 auto plural = "s"[operandInfos.size() == 1];
1680 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1681 " operand type" + plural + " but had " +
1682 llvm::utostr(operandTypes.size())),
1683 nullptr);
1684 }
1685
1686 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001687 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001688 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1689 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001690 return nullptr;
1691 }
1692
Chris Lattner992a1272018-08-07 12:02:37 -07001693 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001694}
1695
1696namespace {
1697class CustomOpAsmParser : public OpAsmParser {
1698public:
1699 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1700 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1701
1702 /// This is an internal helper to parser a colon, we don't want to expose
1703 /// this to clients.
1704 bool internalParseColon(llvm::SMLoc *loc) {
1705 if (loc)
1706 *loc = parser.getToken().getLoc();
1707 return parser.parseToken(Token::colon, "expected ':'");
1708 }
1709
1710 //===--------------------------------------------------------------------===//
1711 // High level parsing methods.
1712 //===--------------------------------------------------------------------===//
1713
1714 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1715 if (loc)
1716 *loc = parser.getToken().getLoc();
1717 return parser.parseToken(Token::comma, "expected ','");
1718 }
1719
1720 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1721 return internalParseColon(loc) || !(result = parser.parseType());
1722 }
1723
1724 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1725 llvm::SMLoc *loc = nullptr) override {
1726 if (internalParseColon(loc))
1727 return true;
1728
1729 do {
1730 if (auto *type = parser.parseType())
1731 result.push_back(type);
1732 else
1733 return true;
1734
1735 } while (parser.consumeIf(Token::comma));
1736 return false;
1737 }
1738
Chris Lattner85cf26d2018-08-02 16:54:36 -07001739 /// Parse an arbitrary attribute and return it in result. This also adds the
1740 /// attribute to the specified attribute list with the specified name. this
1741 /// captures the location of the attribute in 'loc' if it is non-null.
1742 bool parseAttribute(Attribute *&result, const char *attrName,
1743 SmallVectorImpl<NamedAttribute> &attrs,
1744 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001745 if (loc)
1746 *loc = parser.getToken().getLoc();
1747 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001748 if (!result)
1749 return true;
1750
1751 attrs.push_back(
1752 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1753 return false;
1754 }
1755
1756 /// If a named attribute list is present, parse is into result.
1757 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1758 llvm::SMLoc *loc = nullptr) override {
1759 if (parser.getToken().isNot(Token::l_brace))
1760 return false;
1761 if (loc)
1762 *loc = parser.getToken().getLoc();
1763 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001764 }
1765
1766 bool parseOperand(OperandType &result) override {
1767 FunctionParser::SSAUseInfo useInfo;
1768 if (parser.parseSSAUse(useInfo))
1769 return true;
1770
1771 result = {useInfo.loc, useInfo.name, useInfo.number};
1772 return false;
1773 }
1774
1775 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1776 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001777 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001778 auto startLoc = parser.getToken().getLoc();
1779
Chris Lattner85cf26d2018-08-02 16:54:36 -07001780 // Handle delimiters.
1781 switch (delimiter) {
1782 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001783 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001784 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001785 if (parser.getToken().isNot(Token::l_paren))
1786 return false;
1787 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001788 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001789 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1790 return true;
1791 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001792 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001793 if (parser.getToken().isNot(Token::l_square))
1794 return false;
1795 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001796 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001797 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1798 return true;
1799 break;
1800 }
1801
1802 // Check for zero operands.
1803 if (parser.getToken().is(Token::percent_identifier)) {
1804 do {
1805 OperandType operand;
1806 if (parseOperand(operand))
1807 return true;
1808 result.push_back(operand);
1809 } while (parser.consumeIf(Token::comma));
1810 }
1811
Chris Lattner85cf26d2018-08-02 16:54:36 -07001812 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001813 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001814 switch (delimiter) {
1815 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001816 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001817 case Delimiter::OptionalParen:
1818 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001819 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1820 return true;
1821 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001822 case Delimiter::OptionalSquare:
1823 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001824 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1825 return true;
1826 break;
1827 }
1828
1829 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1830 emitError(startLoc,
1831 "expected " + Twine(requiredOperandCount) + " operands");
1832 return false;
1833 }
1834
1835 //===--------------------------------------------------------------------===//
1836 // Methods for interacting with the parser
1837 //===--------------------------------------------------------------------===//
1838
1839 Builder &getBuilder() const override { return parser.builder; }
1840
1841 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1842
1843 bool resolveOperand(OperandType operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001844 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001845 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1846 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001847 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1848 result.push_back(value);
1849 return false;
1850 }
1851 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001852 }
1853
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001854 /// Emit a diagnostic at the specified location and return true.
1855 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001856 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1857 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001858 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001859 }
1860
1861 bool didEmitError() const { return emittedError; }
1862
1863private:
1864 SMLoc nameLoc;
1865 StringRef opName;
1866 FunctionParser &parser;
1867 bool emittedError = false;
1868};
1869} // end anonymous namespace.
1870
1871Operation *FunctionParser::parseCustomOperation(
1872 const CreateOperationFunction &createOpFunc) {
1873 auto opLoc = getToken().getLoc();
1874 auto opName = getTokenSpelling();
1875 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1876
1877 auto *opDefinition = getOperationSet().lookup(opName);
1878 if (!opDefinition) {
1879 opAsmParser.emitError(opLoc, "is unknown");
1880 return nullptr;
1881 }
1882
1883 consumeToken();
1884
1885 // Have the op implementation take a crack and parsing this.
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001886 OperationState opState(builder.getIdentifier(opName));
1887 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1888 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001889
1890 // If it emitted an error, we failed.
1891 if (opAsmParser.didEmitError())
1892 return nullptr;
1893
1894 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001895 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001896}
1897
Chris Lattner48af7d12018-07-09 19:05:38 -07001898//===----------------------------------------------------------------------===//
1899// CFG Functions
1900//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001901
Chris Lattner4c95a502018-06-23 16:03:42 -07001902namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001903/// This is a specialized parser for CFGFunction's, maintaining the state
1904/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001905class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001906public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001907 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001908 : FunctionParser(state, Kind::CFGFunc), function(function),
1909 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001910
1911 ParseResult parseFunctionBody();
1912
1913private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001914 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001915 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001916
1917 /// This builder intentionally shadows the builder in the base class, with a
1918 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001919 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001920
Chris Lattner4c95a502018-06-23 16:03:42 -07001921 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001922 /// already exist. The location specified is the point of use, which allows
1923 /// us to diagnose references to blocks that are not defined precisely.
1924 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1925 auto &blockAndLoc = blocksByName[name];
1926 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001927 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001928 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001929 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001930 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001931 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001932
James Molloy61a656c2018-07-22 15:45:24 -07001933 ParseResult
1934 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1935 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001936 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1937 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001938
Chris Lattner48af7d12018-07-09 19:05:38 -07001939 ParseResult parseBasicBlock();
1940 OperationInst *parseCFGOperation();
1941 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001942};
1943} // end anonymous namespace
1944
James Molloy61a656c2018-07-22 15:45:24 -07001945/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001946/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001947///
1948/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1949///
1950ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1951 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1952 if (getToken().is(Token::r_brace))
1953 return ParseSuccess;
1954
1955 return parseCommaSeparatedList([&]() -> ParseResult {
1956 auto type = parseSSADefOrUseAndType<Type *>(
1957 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1958 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001959 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001960 return nullptr;
1961 return type;
1962 });
1963 return type ? ParseSuccess : ParseFailure;
1964 });
1965}
1966
Chris Lattner48af7d12018-07-09 19:05:38 -07001967ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001968 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001969 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1970 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001971
1972 // Make sure we have at least one block.
1973 if (getToken().is(Token::r_brace))
1974 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001975
1976 // Parse the list of blocks.
1977 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001978 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001979 return ParseFailure;
1980
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001981 // Verify that all referenced blocks were defined. Iteration over a
1982 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001983 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001984 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001985 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001986 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001987 "reference to an undefined basic block '" + elt.first() +
1988 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001989 }
1990
Chris Lattner40746442018-07-21 14:32:09 -07001991 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001992}
1993
1994/// Basic block declaration.
1995///
1996/// basic-block ::= bb-label instruction* terminator-stmt
1997/// bb-label ::= bb-id bb-arg-list? `:`
1998/// bb-id ::= bare-id
1999/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2000///
Chris Lattner48af7d12018-07-09 19:05:38 -07002001ParseResult CFGFunctionParser::parseBasicBlock() {
2002 SMLoc nameLoc = getToken().getLoc();
2003 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002004 if (parseToken(Token::bare_identifier, "expected basic block name"))
2005 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002006
Chris Lattner48af7d12018-07-09 19:05:38 -07002007 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002008
2009 // If this block has already been parsed, then this is a redefinition with the
2010 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002011 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002012 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2013
Chris Lattner78276e32018-07-07 15:48:26 -07002014 // If an argument list is present, parse it.
2015 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002016 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002017 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2018 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002019 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002020 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002021
James Molloy61a656c2018-07-22 15:45:24 -07002022 // Add the block to the function.
2023 function->push_back(block);
2024
Chris Lattnerf7702a62018-07-23 17:30:01 -07002025 if (parseToken(Token::colon, "expected ':' after basic block name"))
2026 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002027
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002028 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002029 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002030
Chris Lattner992a1272018-08-07 12:02:37 -07002031 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2032 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002033 };
2034
Chris Lattnered65a732018-06-28 20:45:33 -07002035 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002036 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002037 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002038 return ParseFailure;
2039 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002040
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002041 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002042 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002043
2044 return ParseSuccess;
2045}
2046
James Molloy4f788372018-07-24 15:01:27 -07002047ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2048 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2049 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2050 if (parseToken(Token::bare_identifier, "expected basic block name"))
2051 return ParseFailure;
2052
2053 if (!consumeIf(Token::l_paren))
2054 return ParseSuccess;
2055 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2056 parseToken(Token::r_paren, "expected ')' to close argument list"))
2057 return ParseFailure;
2058 return ParseSuccess;
2059}
2060
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002061/// Parse the terminator instruction for a basic block.
2062///
2063/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002064/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002065/// terminator-stmt ::=
2066/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2067/// terminator-stmt ::= `return` ssa-use-and-type-list?
2068///
Chris Lattner48af7d12018-07-09 19:05:38 -07002069TerminatorInst *CFGFunctionParser::parseTerminator() {
2070 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002071 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002072 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002073
Chris Lattner40746442018-07-21 14:32:09 -07002074 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002075 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002076
Chris Lattner2c402672018-07-23 11:56:17 -07002077 // Parse any operands.
2078 SmallVector<CFGValue *, 8> operands;
2079 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2080 return nullptr;
2081 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002082 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002083
2084 case Token::kw_br: {
2085 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002086 BasicBlock *destBB;
2087 SmallVector<CFGValue *, 4> values;
2088 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002089 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002090 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002091 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002092 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002093 }
James Molloy4f788372018-07-24 15:01:27 -07002094
2095 case Token::kw_cond_br: {
2096 consumeToken(Token::kw_cond_br);
2097 SSAUseInfo ssaUse;
2098 if (parseSSAUse(ssaUse))
2099 return nullptr;
2100 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2101 if (!cond)
2102 return (emitError("expected type was boolean (i1)"), nullptr);
2103 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2104 return nullptr;
2105
2106 BasicBlock *trueBlock;
2107 SmallVector<CFGValue *, 4> trueOperands;
2108 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2109 return nullptr;
2110
2111 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2112 return nullptr;
2113
2114 BasicBlock *falseBlock;
2115 SmallVector<CFGValue *, 4> falseOperands;
2116 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2117 return nullptr;
2118
2119 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2120 falseBlock);
2121 branch->addTrueOperands(trueOperands);
2122 branch->addFalseOperands(falseOperands);
2123 return branch;
2124 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002125 }
2126}
2127
Chris Lattner48af7d12018-07-09 19:05:38 -07002128//===----------------------------------------------------------------------===//
2129// ML Functions
2130//===----------------------------------------------------------------------===//
2131
2132namespace {
2133/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002134class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002135public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002136 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002137 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002138 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002139
2140 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002141
2142private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002143 MLFunction *function;
2144
2145 /// This builder intentionally shadows the builder in the base class, with a
2146 /// more specific builder type.
2147 MLFuncBuilder builder;
2148
2149 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002150 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002151 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002152 ParseResult parseElseClause(IfClause *elseClause);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002153 IntegerSet *parseCondition();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002154 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002155 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002156};
2157} // end anonymous namespace
2158
Chris Lattner48af7d12018-07-09 19:05:38 -07002159ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002160 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002161
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002162 // Parse statements in this function.
2163 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002164 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002165
Chris Lattner40746442018-07-21 14:32:09 -07002166 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002167}
2168
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002169/// For statement.
2170///
Chris Lattner48af7d12018-07-09 19:05:38 -07002171/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2172/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002173///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002174ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002175 consumeToken(Token::kw_for);
2176
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002177 // Parse induction variable
2178 if (getToken().isNot(Token::percent_identifier))
2179 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002180
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002181 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002182 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002183 consumeToken(Token::percent_identifier);
2184
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002185 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002186 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002187
2188 // Parse loop bounds
2189 AffineConstantExpr *lowerBound = parseIntConstant();
2190 if (!lowerBound)
2191 return ParseFailure;
2192
Chris Lattnerf7702a62018-07-23 17:30:01 -07002193 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2194 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002195
2196 AffineConstantExpr *upperBound = parseIntConstant();
2197 if (!upperBound)
2198 return ParseFailure;
2199
2200 // Parse step
2201 AffineConstantExpr *step = nullptr;
2202 if (consumeIf(Token::kw_step)) {
2203 step = parseIntConstant();
2204 if (!step)
2205 return ParseFailure;
2206 }
2207
2208 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002209 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2210
2211 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002212 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2213 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002214
2215 // If parsing of the for statement body fails,
2216 // MLIR contains for statement with those nested statements that have been
2217 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002218 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002219 return ParseFailure;
2220
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002221 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002222 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002223
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002224 // TODO: remove definition of the induction variable.
2225
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002226 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002227}
2228
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002229// This method is temporary workaround to parse simple loop bounds and
2230// step.
2231// TODO: remove this method once it's no longer used.
2232AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2233 if (getToken().isNot(Token::integer))
2234 return (emitError("expected non-negative integer for now"), nullptr);
2235
2236 auto val = getToken().getUInt64IntegerValue();
2237 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2238 return (emitError("constant too large for affineint"), nullptr);
2239 }
2240 consumeToken(Token::integer);
2241 return builder.getConstantExpr((int64_t)val.getValue());
2242}
2243
Uday Bondhugulabc535622018-08-07 14:24:38 -07002244/// Parse condition.
2245IntegerSet *MLFunctionParser::parseCondition() {
2246 return parseIntegerSetReference();
2247
2248 // TODO: Parse operands to the integer set.
2249}
2250
2251/// Parse an affine constraint.
2252/// affine-constraint ::= affine-expr `>=` `0`
2253/// | affine-expr `==` `0`
2254///
2255/// isEq is set to true if the parsed constraint is an equality, false if it is
2256/// an inequality (greater than or equal).
2257///
2258AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2259 AffineExpr *expr = parseAffineExpr();
2260 if (!expr)
2261 return nullptr;
2262
2263 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2264 getToken().is(Token::integer)) {
2265 auto dim = getToken().getUnsignedIntegerValue();
2266 if (dim.hasValue() && dim.getValue() == 0) {
2267 consumeToken(Token::integer);
2268 *isEq = false;
2269 return expr;
2270 }
2271 return (emitError("expected '0' after '>='"), nullptr);
2272 }
2273
2274 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2275 getToken().is(Token::integer)) {
2276 auto dim = getToken().getUnsignedIntegerValue();
2277 if (dim.hasValue() && dim.getValue() == 0) {
2278 consumeToken(Token::integer);
2279 *isEq = true;
2280 return expr;
2281 }
2282 return (emitError("expected '0' after '=='"), nullptr);
2283 }
2284
2285 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2286 nullptr);
2287}
2288
2289/// Parse an integer set definition.
2290/// integer-set-inline
2291/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2292/// affine-constraint-conjunction ::= /*empty*/
2293/// | affine-constraint (`,` affine-constraint)*
2294///
2295IntegerSet *AffineParser::parseIntegerSetInline() {
2296 unsigned numDims = 0, numSymbols = 0;
2297
2298 // List of dimensional identifiers.
2299 if (parseDimIdList(numDims))
2300 return nullptr;
2301
2302 // Symbols are optional.
2303 if (getToken().is(Token::l_square)) {
2304 if (parseSymbolIdList(numSymbols))
2305 return nullptr;
2306 }
2307
2308 if (parseToken(Token::colon, "expected ':' or '['") ||
2309 parseToken(Token::l_paren,
2310 "expected '(' at start of integer set constraint list"))
2311 return nullptr;
2312
2313 SmallVector<AffineExpr *, 4> constraints;
2314 SmallVector<bool, 4> isEqs;
2315 auto parseElt = [&]() -> ParseResult {
2316 bool isEq;
2317 auto *elt = parseAffineConstraint(&isEq);
2318 ParseResult res = elt ? ParseSuccess : ParseFailure;
2319 if (elt) {
2320 constraints.push_back(elt);
2321 isEqs.push_back(isEq);
2322 }
2323 return res;
2324 };
2325
2326 // Parse a list of affine constraints (comma-separated) .
2327 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2328 // affine-constraint)* `)
2329 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2330 return nullptr;
2331
2332 // Parsed a valid integer set.
2333 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2334}
2335
2336IntegerSet *Parser::parseIntegerSetInline() {
2337 return AffineParser(state).parseIntegerSetInline();
2338}
2339
2340/// Parse a reference to an integer set.
2341/// integer-set ::= integer-set-id | integer-set-inline
2342/// integer-set-id ::= `@@` suffix-id
2343///
2344IntegerSet *Parser::parseIntegerSetReference() {
2345 if (getToken().is(Token::double_at_identifier)) {
2346 // Parse integer set identifier and verify that it exists.
2347 StringRef integerSetId = getTokenSpelling().drop_front(2);
2348 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2349 return (emitError("undefined integer set id '" + integerSetId + "'"),
2350 nullptr);
2351 consumeToken(Token::double_at_identifier);
2352 return getState().integerSetDefinitions[integerSetId];
2353 }
2354 // Try to parse an inline integer set definition.
2355 return parseIntegerSetInline();
2356}
2357
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002358/// If statement.
2359///
Chris Lattner48af7d12018-07-09 19:05:38 -07002360/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2361/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2362/// ml-if-stmt ::= ml-if-head
2363/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002364///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002365ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002366 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002367
2368 if (parseToken(Token::l_paren, "expected '('"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002369 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002370
Uday Bondhugulabc535622018-08-07 14:24:38 -07002371 IntegerSet *condition = parseCondition();
2372 if (!condition)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002373 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002374
Uday Bondhugulabc535622018-08-07 14:24:38 -07002375 if (parseToken(Token::r_paren, "expected ')'"))
2376 return ParseFailure;
2377
2378 IfStmt *ifStmt = builder.createIf(condition);
Chris Lattnere787b322018-08-08 11:14:57 -07002379 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002380
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002381 // When parsing of an if statement body fails, the IR contains
2382 // the if statement with the portion of the body that has been
2383 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002384 if (parseStmtBlock(thenClause))
2385 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002386
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002387 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002388 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002389 if (parseElseClause(elseClause))
2390 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002391 }
2392
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002393 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002394 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002395
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002396 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002397}
2398
2399ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2400 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002401 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002402 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002403 }
2404
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002405 return parseStmtBlock(elseClause);
2406}
2407
2408///
2409/// Parse a list of statements ending with `return` or `}`
2410///
2411ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002412 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2413 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002414 };
2415
Chris Lattnere787b322018-08-08 11:14:57 -07002416 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002417
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002418 // Parse statements till we see '}' or 'return'.
2419 // Return statement is parsed separately to emit a more intuitive error
2420 // when '}' is missing after the return statement.
2421 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002422 switch (getToken().getKind()) {
2423 default:
2424 if (parseOperation(createOpFunc))
2425 return ParseFailure;
2426 break;
2427 case Token::kw_for:
2428 if (parseForStmt())
2429 return ParseFailure;
2430 break;
2431 case Token::kw_if:
2432 if (parseIfStmt())
2433 return ParseFailure;
2434 break;
2435 } // end switch
2436 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002437
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002438 // Parse the return statement.
2439 if (getToken().is(Token::kw_return))
2440 if (parseOperation(createOpFunc))
2441 return ParseFailure;
2442
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002443 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002444}
2445
2446///
2447/// Parse `{` ml-stmt* `}`
2448///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002449ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002450 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2451 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002452 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002453 return ParseFailure;
2454
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002455 return ParseSuccess;
2456}
2457
Chris Lattner4c95a502018-06-23 16:03:42 -07002458//===----------------------------------------------------------------------===//
2459// Top-level entity parsing.
2460//===----------------------------------------------------------------------===//
2461
Chris Lattner2e595eb2018-07-10 10:08:27 -07002462namespace {
2463/// This parser handles entities that are only valid at the top level of the
2464/// file.
2465class ModuleParser : public Parser {
2466public:
2467 explicit ModuleParser(ParserState &state) : Parser(state) {}
2468
2469 ParseResult parseModule();
2470
2471private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002472 ParseResult finalizeModule();
2473
Chris Lattner2e595eb2018-07-10 10:08:27 -07002474 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002475 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002476
2477 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002478 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2479 SmallVectorImpl<StringRef> &argNames);
2480 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2481 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002482 ParseResult parseExtFunc();
2483 ParseResult parseCFGFunc();
2484 ParseResult parseMLFunc();
2485};
2486} // end anonymous namespace
2487
2488/// Affine map declaration.
2489///
2490/// affine-map-def ::= affine-map-id `=` affine-map-inline
2491///
2492ParseResult ModuleParser::parseAffineMapDef() {
2493 assert(getToken().is(Token::hash_identifier));
2494
2495 StringRef affineMapId = getTokenSpelling().drop_front();
2496
2497 // Check for redefinitions.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002498 auto **entry = &getState().affineMapDefinitions[affineMapId];
2499 if (*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002500 return emitError("redefinition of affine map id '" + affineMapId + "'");
2501
2502 consumeToken(Token::hash_identifier);
2503
2504 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002505 if (parseToken(Token::equal,
2506 "expected '=' in affine map outlined definition"))
2507 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002508
Uday Bondhugulabc535622018-08-07 14:24:38 -07002509 *entry = parseAffineMapInline();
2510 if (!*entry)
2511 return ParseFailure;
2512
2513 return ParseSuccess;
2514}
2515
2516/// Integer set declaration.
2517///
2518/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2519///
2520ParseResult ModuleParser::parseIntegerSetDef() {
2521 assert(getToken().is(Token::double_at_identifier));
2522
2523 StringRef integerSetId = getTokenSpelling().drop_front(2);
2524
2525 // Check for redefinitions (a default entry is created if one doesn't exist)
2526 auto **entry = &getState().integerSetDefinitions[integerSetId];
2527 if (*entry)
2528 return emitError("redefinition of integer set id '" + integerSetId + "'");
2529
2530 consumeToken(Token::double_at_identifier);
2531
2532 // Parse the '='
2533 if (parseToken(Token::equal,
2534 "expected '=' in outlined integer set definition"))
2535 return ParseFailure;
2536
2537 *entry = parseIntegerSetInline();
2538 if (!*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002539 return ParseFailure;
2540
Chris Lattner2e595eb2018-07-10 10:08:27 -07002541 return ParseSuccess;
2542}
2543
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002544/// Parse a (possibly empty) list of MLFunction arguments with types.
2545///
2546/// ml-argument ::= ssa-id `:` type
2547/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2548///
2549ParseResult
2550ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2551 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002552 consumeToken(Token::l_paren);
2553
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002554 auto parseElt = [&]() -> ParseResult {
2555 // Parse argument name
2556 if (getToken().isNot(Token::percent_identifier))
2557 return emitError("expected SSA identifier");
2558
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002559 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002560 consumeToken(Token::percent_identifier);
2561 argNames.push_back(name);
2562
Chris Lattnerf7702a62018-07-23 17:30:01 -07002563 if (parseToken(Token::colon, "expected ':'"))
2564 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002565
2566 // Parse argument type
2567 auto elt = parseType();
2568 if (!elt)
2569 return ParseFailure;
2570 argTypes.push_back(elt);
2571
2572 return ParseSuccess;
2573 };
2574
Chris Lattner40746442018-07-21 14:32:09 -07002575 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002576}
2577
Chris Lattner2e595eb2018-07-10 10:08:27 -07002578/// Parse a function signature, starting with a name and including the parameter
2579/// list.
2580///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002581/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002582/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2583///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002584ParseResult
2585ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2586 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002587 if (getToken().isNot(Token::at_identifier))
2588 return emitError("expected a function identifier like '@foo'");
2589
2590 name = getTokenSpelling().drop_front();
2591 consumeToken(Token::at_identifier);
2592
2593 if (getToken().isNot(Token::l_paren))
2594 return emitError("expected '(' in function signature");
2595
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002596 SmallVector<Type *, 4> argTypes;
2597 ParseResult parseResult;
2598
2599 if (argNames)
2600 parseResult = parseMLArgumentList(argTypes, *argNames);
2601 else
2602 parseResult = parseTypeList(argTypes);
2603
2604 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002605 return ParseFailure;
2606
2607 // Parse the return type if present.
2608 SmallVector<Type *, 4> results;
2609 if (consumeIf(Token::arrow)) {
2610 if (parseTypeList(results))
2611 return ParseFailure;
2612 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002613 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002614 return ParseSuccess;
2615}
2616
2617/// External function declarations.
2618///
2619/// ext-func ::= `extfunc` function-signature
2620///
2621ParseResult ModuleParser::parseExtFunc() {
2622 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002623 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002624
2625 StringRef name;
2626 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002627 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002628 return ParseFailure;
2629
2630 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002631 auto *function = new ExtFunction(name, type);
2632 getModule()->getFunctions().push_back(function);
2633
2634 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002635 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002636 return emitError(loc,
2637 "redefinition of function named '" + name.str() + "'");
2638
Chris Lattner2e595eb2018-07-10 10:08:27 -07002639 return ParseSuccess;
2640}
2641
2642/// CFG function declarations.
2643///
2644/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2645///
2646ParseResult ModuleParser::parseCFGFunc() {
2647 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002648 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002649
2650 StringRef name;
2651 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002652 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002653 return ParseFailure;
2654
2655 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002656 auto *function = new CFGFunction(name, type);
2657 getModule()->getFunctions().push_back(function);
2658
2659 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002660 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002661 return emitError(loc,
2662 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002663
2664 return CFGFunctionParser(getState(), function).parseFunctionBody();
2665}
2666
2667/// ML function declarations.
2668///
2669/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2670///
2671ParseResult ModuleParser::parseMLFunc() {
2672 consumeToken(Token::kw_mlfunc);
2673
2674 StringRef name;
2675 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002676 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002677
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002678 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002679 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002680 return ParseFailure;
2681
2682 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002683 auto *function = MLFunction::create(name, type);
2684 getModule()->getFunctions().push_back(function);
2685
2686 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002687 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002688 return emitError(loc,
2689 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002690
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002691 // Create the parser.
2692 auto parser = MLFunctionParser(getState(), function);
2693
2694 // Add definitions of the function arguments.
2695 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2696 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2697 return ParseFailure;
2698 }
2699
2700 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002701}
2702
Chris Lattner4613d9e2018-08-19 21:17:22 -07002703/// Finish the end of module parsing - when the result is valid, do final
2704/// checking.
2705ParseResult ModuleParser::finalizeModule() {
2706
2707 // Resolve all forward references.
2708 for (auto forwardRef : getState().functionForwardRefs) {
2709 auto name = forwardRef.first;
2710
2711 // Resolve the reference.
2712 auto *resolvedFunction = getModule()->getNamedFunction(name);
2713 if (!resolvedFunction)
2714 return emitError(forwardRef.second.second,
2715 "reference to undefined function '" + name.str() + "'");
2716
2717 // TODO(clattner): actually go through and update references in the module
2718 // to the new function.
2719 }
2720
2721 return ParseSuccess;
2722}
2723
Chris Lattnere79379a2018-06-22 10:39:19 -07002724/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002725ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002726 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002727 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002728 default:
2729 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002730 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002731
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002732 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002733 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002734 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002735
2736 // If we got an error token, then the lexer already emitted an error, just
2737 // stop. Someday we could introduce error recovery if there was demand for
2738 // it.
2739 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002740 return ParseFailure;
2741
2742 case Token::hash_identifier:
2743 if (parseAffineMapDef())
2744 return ParseFailure;
2745 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002746
Uday Bondhugulabc535622018-08-07 14:24:38 -07002747 case Token::double_at_identifier:
2748 if (parseIntegerSetDef())
2749 return ParseFailure;
2750 break;
2751
Chris Lattnere79379a2018-06-22 10:39:19 -07002752 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002753 if (parseExtFunc())
2754 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002755 break;
2756
Chris Lattner4c95a502018-06-23 16:03:42 -07002757 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002758 if (parseCFGFunc())
2759 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002760 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002761
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002762 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002763 if (parseMLFunc())
2764 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002765 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002766 }
2767 }
2768}
2769
2770//===----------------------------------------------------------------------===//
2771
Jacques Pienaar7b829702018-07-03 13:24:09 -07002772void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2773 const auto &sourceMgr = *error.getSourceMgr();
2774 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2775}
2776
Chris Lattnere79379a2018-06-22 10:39:19 -07002777/// This parses the file specified by the indicated SourceMgr and returns an
2778/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002779Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002780 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002781 // This is the result module we are parsing into.
2782 std::unique_ptr<Module> module(new Module(context));
2783
2784 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002785 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002786 if (ModuleParser(state).parseModule())
2787 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002788
2789 // Make sure the parse module has no other structural problems detected by the
2790 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002791 module->verify();
2792 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002793}