blob: 154a24c549660b9c2014f616b12d755f8ff324d8 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -070028#include "mlir/IR/IntegerSet.h"
Chris Lattnerfc647d52018-08-27 21:05:16 -070029#include "mlir/IR/Location.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070030#include "mlir/IR/MLFunction.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070031#include "mlir/IR/MLIRContext.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070032#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070033#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070034#include "mlir/IR/OperationSet.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070035#include "mlir/IR/StmtVisitor.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070036#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070037#include "llvm/ADT/DenseMap.h"
Jacques Pienaarbd22d432018-09-03 07:38:31 -070038#include "llvm/Support/MemoryBuffer.h"
Chris Lattner1aa46322018-08-21 17:55:22 -070039#include "llvm/Support/PrettyStackTrace.h"
Jacques Pienaarbd22d432018-09-03 07:38:31 -070040#include "llvm/Support/SMLoc.h"
James Molloyf0d2f442018-08-03 01:54:46 -070041#include "llvm/Support/SourceMgr.h"
Jacques Pienaarbd22d432018-09-03 07:38:31 -070042
Chris Lattnere79379a2018-06-22 10:39:19 -070043using namespace mlir;
Jacques Pienaarbd22d432018-09-03 07:38:31 -070044using llvm::MemoryBuffer;
Chris Lattner4c95a502018-06-23 16:03:42 -070045using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070046using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070047
Chris Lattnerf7e22732018-06-22 22:03:48 -070048/// Simple enum to make code read better in cases that would otherwise return a
49/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070050enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070051
Chris Lattner48af7d12018-07-09 19:05:38 -070052namespace {
53class Parser;
54
55/// This class refers to all of the state maintained globally by the parser,
56/// such as the current lexer position etc. The Parser base class provides
57/// methods to access this.
58class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070059public:
Chris Lattner7879f842018-09-02 22:01:45 -070060 ParserState(llvm::SourceMgr &sourceMgr, Module *module)
61 : context(module->getContext()), module(module), lex(sourceMgr, context),
62 curToken(lex.lexToken()), operationSet(OperationSet::get(context)) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070063
64 // A map from affine map identifier to AffineMap.
65 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070066
Uday Bondhugulabc535622018-08-07 14:24:38 -070067 // A map from integer set identifier to IntegerSet.
68 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070069
Chris Lattner4613d9e2018-08-19 21:17:22 -070070 // This keeps track of all forward references to functions along with the
71 // temporary function used to represent them and the location of the first
72 // reference.
73 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
74
Chris Lattnere79379a2018-06-22 10:39:19 -070075private:
Chris Lattner48af7d12018-07-09 19:05:38 -070076 ParserState(const ParserState &) = delete;
77 void operator=(const ParserState &) = delete;
78
79 friend class Parser;
80
81 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070082 MLIRContext *const context;
83
84 // This is the module we are parsing into.
85 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070086
87 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070088 Lexer lex;
89
90 // This is the next token that hasn't been consumed yet.
91 Token curToken;
92
Chris Lattner85ee1512018-07-25 11:15:20 -070093 // The active OperationSet we're parsing with.
94 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070095};
96} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070097
Chris Lattner48af7d12018-07-09 19:05:38 -070098namespace {
99
Chris Lattner992a1272018-08-07 12:02:37 -0700100typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700101 CreateOperationFunction;
102
Chris Lattner48af7d12018-07-09 19:05:38 -0700103/// This class implement support for parsing global entities like types and
104/// shared entities like SSA names. It is intended to be subclassed by
105/// specialized subparsers that include state, e.g. when a local symbol table.
106class Parser {
107public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700108 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700109
Chris Lattner2e595eb2018-07-10 10:08:27 -0700110 Parser(ParserState &state) : builder(state.context), state(state) {}
111
112 // Helper methods to get stuff from the parser-global state.
113 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700114 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700115 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700116 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700117 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700118
119 /// Return the current token the parser is inspecting.
120 const Token &getToken() const { return state.curToken; }
121 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700122
Chris Lattner1628fa02018-08-23 14:32:25 -0700123 /// Encode the specified source location information into an attribute for
124 /// attachment to the IR.
Chris Lattner7879f842018-09-02 22:01:45 -0700125 Location *getEncodedSourceLocation(llvm::SMLoc loc) {
126 return state.lex.getEncodedSourceLocation(loc);
127 }
Chris Lattner1628fa02018-08-23 14:32:25 -0700128
Chris Lattnere79379a2018-06-22 10:39:19 -0700129 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700130 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700131 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700132 }
133 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700134
135 /// Advance the current lexer onto the next token.
136 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700137 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700138 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700139 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700140 }
141
142 /// Advance the current lexer onto the next token, asserting what the expected
143 /// current token is. This is preferred to the above method because it leads
144 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700145 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700146 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700147 consumeToken();
148 }
149
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700150 /// If the current token has the specified kind, consume it and return true.
151 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700152 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700153 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700154 return false;
155 consumeToken(kind);
156 return true;
157 }
158
Chris Lattnerf7702a62018-07-23 17:30:01 -0700159 /// Consume the specified token if present and return success. On failure,
160 /// output a diagnostic and return failure.
161 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
162
Chris Lattner40746442018-07-21 14:32:09 -0700163 /// Parse a comma-separated list of elements up until the specified end token.
164 ParseResult
165 parseCommaSeparatedListUntil(Token::Kind rightToken,
166 const std::function<ParseResult()> &parseElement,
167 bool allowEmptyList = true);
168
169 /// Parse a comma separated list of elements that must have at least one entry
170 /// in it.
171 ParseResult
172 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700173
Chris Lattnerf7e22732018-06-22 22:03:48 -0700174 // We have two forms of parsing methods - those that return a non-null
175 // pointer on success, and those that return a ParseResult to indicate whether
176 // they returned a failure. The second class fills in by-reference arguments
177 // as the results of their action.
178
Chris Lattnere79379a2018-06-22 10:39:19 -0700179 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700180 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700181 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700182 Type *parseTensorType();
183 Type *parseMemRefType();
184 Type *parseFunctionType();
185 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700186 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700187 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700188
Chris Lattner7121b802018-07-04 20:45:39 -0700189 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700190 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
191 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700192 Attribute *parseAttribute();
193 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
194
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700195 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700196 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700197 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700198 IntegerSet *parseIntegerSetInline();
199 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700200
Chris Lattner48af7d12018-07-09 19:05:38 -0700201private:
202 // The Parser is subclassed and reinstantiated. Do not add additional
203 // non-trivial state here, add it to the ParserState class.
204 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700205};
206} // end anonymous namespace
207
208//===----------------------------------------------------------------------===//
209// Helper methods.
210//===----------------------------------------------------------------------===//
211
Chris Lattner4c95a502018-06-23 16:03:42 -0700212ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700213 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700214 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700215 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700216 return ParseFailure;
217
Chris Lattner7879f842018-09-02 22:01:45 -0700218 getContext()->emitDiagnostic(getEncodedSourceLocation(loc), message,
219 MLIRContext::DiagnosticKind::Error);
Chris Lattnere79379a2018-06-22 10:39:19 -0700220 return ParseFailure;
221}
222
Chris Lattnerf7702a62018-07-23 17:30:01 -0700223/// Consume the specified token if present and return success. On failure,
224/// output a diagnostic and return failure.
225ParseResult Parser::parseToken(Token::Kind expectedToken,
226 const Twine &message) {
227 if (consumeIf(expectedToken))
228 return ParseSuccess;
229 return emitError(message);
230}
231
Chris Lattner40746442018-07-21 14:32:09 -0700232/// Parse a comma separated list of elements that must have at least one entry
233/// in it.
234ParseResult Parser::parseCommaSeparatedList(
235 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700236 // Non-empty case starts with an element.
237 if (parseElement())
238 return ParseFailure;
239
240 // Otherwise we have a list of comma separated elements.
241 while (consumeIf(Token::comma)) {
242 if (parseElement())
243 return ParseFailure;
244 }
Chris Lattner40746442018-07-21 14:32:09 -0700245 return ParseSuccess;
246}
247
248/// Parse a comma-separated list of elements, terminated with an arbitrary
249/// token. This allows empty lists if allowEmptyList is true.
250///
251/// abstract-list ::= rightToken // if allowEmptyList == true
252/// abstract-list ::= element (',' element)* rightToken
253///
254ParseResult Parser::parseCommaSeparatedListUntil(
255 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
256 bool allowEmptyList) {
257 // Handle the empty case.
258 if (getToken().is(rightToken)) {
259 if (!allowEmptyList)
260 return emitError("expected list element");
261 consumeToken(rightToken);
262 return ParseSuccess;
263 }
264
Chris Lattnerf7702a62018-07-23 17:30:01 -0700265 if (parseCommaSeparatedList(parseElement) ||
266 parseToken(rightToken, "expected ',' or '" +
267 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700268 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700270 return ParseSuccess;
271}
Chris Lattnere79379a2018-06-22 10:39:19 -0700272
273//===----------------------------------------------------------------------===//
274// Type Parsing
275//===----------------------------------------------------------------------===//
276
Chris Lattnerc3251192018-07-27 13:09:58 -0700277/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700278///
Chris Lattnerc3251192018-07-27 13:09:58 -0700279/// type ::= integer-type
280/// | float-type
281/// | other-type
282/// | vector-type
283/// | tensor-type
284/// | memref-type
285/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700286///
Chris Lattnerc3251192018-07-27 13:09:58 -0700287/// float-type ::= `f16` | `bf16` | `f32` | `f64`
288/// other-type ::= `affineint` | `tf_control`
289///
290Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700291 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700292 default:
293 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700294 case Token::kw_memref:
295 return parseMemRefType();
296 case Token::kw_tensor:
297 return parseTensorType();
298 case Token::kw_vector:
299 return parseVectorType();
300 case Token::l_paren:
301 return parseFunctionType();
302 // integer-type
303 case Token::inttype: {
304 auto width = getToken().getIntTypeBitwidth();
305 if (!width.hasValue())
306 return (emitError("invalid integer width"), nullptr);
Nicolas Vasilache1b8c0842018-08-27 10:26:15 -0700307 if (width > IntegerType::kMaxWidth)
308 return (emitError("integer bitwidth is limited to " +
309 Twine(IntegerType::kMaxWidth) + " bits"),
310 nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700311 consumeToken(Token::inttype);
312 return builder.getIntegerType(width.getValue());
313 }
314
315 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700316 case Token::kw_bf16:
317 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700318 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700319 case Token::kw_f16:
320 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700321 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700322 case Token::kw_f32:
323 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700324 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700325 case Token::kw_f64:
326 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700327 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700328
329 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700330 case Token::kw_affineint:
331 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700332 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700333 case Token::kw_tf_control:
334 consumeToken(Token::kw_tf_control);
335 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700336 case Token::kw_tf_string:
337 consumeToken(Token::kw_tf_string);
338 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700339 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700340}
341
342/// Parse a vector type.
343///
344/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
345/// const-dimension-list ::= (integer-literal `x`)+
346///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700347VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348 consumeToken(Token::kw_vector);
349
Chris Lattnerf7702a62018-07-23 17:30:01 -0700350 if (parseToken(Token::less, "expected '<' in vector type"))
351 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700352
Chris Lattner48af7d12018-07-09 19:05:38 -0700353 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700354 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700355
356 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700357 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700358 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700359 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700361 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700362 dimensions.push_back(dimension.getValue());
363
364 consumeToken(Token::integer);
365
366 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700367 if (getToken().isNot(Token::bare_identifier) ||
368 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700369 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700370
371 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700372 if (getTokenSpelling().size() != 1)
373 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700374
375 // Consume the 'x'.
376 consumeToken(Token::bare_identifier);
377 }
378
379 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700380 auto typeLoc = getToken().getLoc();
381 auto *elementType = parseType();
382 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700383 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700384
Chris Lattnerc3251192018-07-27 13:09:58 -0700385 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
386 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700387
Chris Lattnerf7e22732018-06-22 22:03:48 -0700388 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700389}
390
391/// Parse a dimension list of a tensor or memref type. This populates the
392/// dimension list, returning -1 for the '?' dimensions.
393///
394/// dimension-list-ranked ::= (dimension `x`)*
395/// dimension ::= `?` | integer-literal
396///
397ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700398 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700399 if (consumeIf(Token::question)) {
400 dimensions.push_back(-1);
401 } else {
402 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700403 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700404 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
405 return emitError("invalid dimension");
406 dimensions.push_back((int)dimension.getValue());
407 consumeToken(Token::integer);
408 }
409
410 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700411 if (getToken().isNot(Token::bare_identifier) ||
412 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700413 return emitError("expected 'x' in dimension list");
414
415 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700416 if (getTokenSpelling().size() != 1)
417 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700418
419 // Consume the 'x'.
420 consumeToken(Token::bare_identifier);
421 }
422
423 return ParseSuccess;
424}
425
426/// Parse a tensor type.
427///
428/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
429/// dimension-list ::= dimension-list-ranked | `??`
430///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700431Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700432 consumeToken(Token::kw_tensor);
433
Chris Lattnerf7702a62018-07-23 17:30:01 -0700434 if (parseToken(Token::less, "expected '<' in tensor type"))
435 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700436
437 bool isUnranked;
438 SmallVector<int, 4> dimensions;
439
440 if (consumeIf(Token::questionquestion)) {
441 isUnranked = true;
442 } else {
443 isUnranked = false;
444 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700445 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700446 }
447
448 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700449 auto typeLoc = getToken().getLoc();
450 auto *elementType = parseType();
451 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700452 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700453
Chris Lattnerc3251192018-07-27 13:09:58 -0700454 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
455 !isa<VectorType>(elementType))
456 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700457
MLIR Team355ec862018-06-23 18:09:09 -0700458 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700459 return builder.getTensorType(elementType);
460 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700461}
462
463/// Parse a memref type.
464///
465/// memref-type ::= `memref` `<` dimension-list-ranked element-type
466/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
467///
468/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
469/// memory-space ::= integer-literal /* | TODO: address-space-id */
470///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700471Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700472 consumeToken(Token::kw_memref);
473
Chris Lattnerf7702a62018-07-23 17:30:01 -0700474 if (parseToken(Token::less, "expected '<' in memref type"))
475 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700476
477 SmallVector<int, 4> dimensions;
478 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700479 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700480
481 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700482 auto typeLoc = getToken().getLoc();
483 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700484 if (!elementType)
485 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700486
Chris Lattnerc3251192018-07-27 13:09:58 -0700487 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
488 !isa<VectorType>(elementType))
489 return (emitError(typeLoc, "invalid memref element type"), nullptr);
490
MLIR Team718c82f2018-07-16 09:45:22 -0700491 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700492 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700493 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700494 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700495
MLIR Team718c82f2018-07-16 09:45:22 -0700496 auto parseElt = [&]() -> ParseResult {
497 if (getToken().is(Token::integer)) {
498 // Parse memory space.
499 if (parsedMemorySpace)
500 return emitError("multiple memory spaces specified in memref type");
501 auto v = getToken().getUnsignedIntegerValue();
502 if (!v.hasValue())
503 return emitError("invalid memory space in memref type");
504 memorySpace = v.getValue();
505 consumeToken(Token::integer);
506 parsedMemorySpace = true;
507 } else {
508 // Parse affine map.
509 if (parsedMemorySpace)
510 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700511 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700512 if (affineMap == nullptr)
513 return ParseFailure;
514 affineMapComposition.push_back(affineMap);
515 }
516 return ParseSuccess;
517 };
518
Chris Lattner413db6a2018-07-25 12:55:50 -0700519 // Parse a list of mappings and address space if present.
520 if (consumeIf(Token::comma)) {
521 // Parse comma separated list of affine maps, followed by memory space.
522 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
523 /*allowEmptyList=*/false)) {
524 return nullptr;
525 }
526 } else {
527 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
528 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700529 }
MLIR Team718c82f2018-07-16 09:45:22 -0700530
531 return MemRefType::get(dimensions, elementType, affineMapComposition,
532 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700533}
534
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700535/// Parse a function type.
536///
537/// function-type ::= type-list-parens `->` type-list
538///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700539Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700540 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700541
Chris Lattnerf7702a62018-07-23 17:30:01 -0700542 SmallVector<Type *, 4> arguments, results;
543 if (parseTypeList(arguments) ||
544 parseToken(Token::arrow, "expected '->' in function type") ||
545 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700546 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700547
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700548 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700549}
550
Chris Lattner1604e472018-07-23 08:42:19 -0700551/// Parse a list of types without an enclosing parenthesis. The list must have
552/// at least one member.
553///
554/// type-list-no-parens ::= type (`,` type)*
555///
556ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
557 auto parseElt = [&]() -> ParseResult {
558 auto elt = parseType();
559 elements.push_back(elt);
560 return elt ? ParseSuccess : ParseFailure;
561 };
562
563 return parseCommaSeparatedList(parseElt);
564}
565
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700566/// Parse a "type list", which is a singular type, or a parenthesized list of
567/// types.
568///
569/// type-list ::= type-list-parens | type
570/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700571/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700572///
James Molloy0ff71542018-07-23 16:56:32 -0700573ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700574 auto parseElt = [&]() -> ParseResult {
575 auto elt = parseType();
576 elements.push_back(elt);
577 return elt ? ParseSuccess : ParseFailure;
578 };
579
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700580 // If there is no parens, then it must be a singular type.
581 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700582 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700583
Chris Lattner40746442018-07-21 14:32:09 -0700584 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700585 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700586
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700587 return ParseSuccess;
588}
589
Chris Lattner4c95a502018-06-23 16:03:42 -0700590//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700591// Attribute parsing.
592//===----------------------------------------------------------------------===//
593
Chris Lattner1aa46322018-08-21 17:55:22 -0700594/// Given a parsed reference to a function name like @foo and a type that it
595/// corresponds to, resolve it to a concrete function object (possibly
596/// synthesizing a forward reference) or emit an error and return null on
597/// failure.
598Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
599 FunctionType *type) {
600 Identifier name = builder.getIdentifier(nameStr.drop_front());
601
602 // See if the function has already been defined in the module.
603 Function *function = getModule()->getNamedFunction(name);
604
605 // If not, get or create a forward reference to one.
606 if (!function) {
607 auto &entry = state.functionForwardRefs[name];
608 if (!entry.first) {
609 entry.first = new ExtFunction(name, type);
610 entry.second = nameLoc;
611 }
612 function = entry.first;
613 }
614
615 if (function->getType() != type)
616 return (emitError(nameLoc, "reference to function with mismatched type"),
617 nullptr);
618 return function;
619}
620
Chris Lattner7121b802018-07-04 20:45:39 -0700621/// Attribute parsing.
622///
623/// attribute-value ::= bool-literal
624/// | integer-literal
625/// | float-literal
626/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700627/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700628/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700629/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700630///
631Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700632 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700633 case Token::kw_true:
634 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700635 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700636 case Token::kw_false:
637 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700638 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700639
Jacques Pienaar84491092018-07-31 17:15:15 -0700640 case Token::floatliteral: {
641 auto val = getToken().getFloatingPointValue();
642 if (!val.hasValue())
643 return (emitError("floating point value too large for attribute"),
644 nullptr);
645 consumeToken(Token::floatliteral);
646 return builder.getFloatAttr(val.getValue());
647 }
Chris Lattner7121b802018-07-04 20:45:39 -0700648 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700649 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700650 if (!val.hasValue() || (int64_t)val.getValue() < 0)
651 return (emitError("integer too large for attribute"), nullptr);
652 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700653 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700654 }
655
656 case Token::minus: {
657 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700658 if (getToken().is(Token::integer)) {
659 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700660 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
661 return (emitError("integer too large for attribute"), nullptr);
662 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700663 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700664 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700665 if (getToken().is(Token::floatliteral)) {
666 auto val = getToken().getFloatingPointValue();
667 if (!val.hasValue())
668 return (emitError("floating point value too large for attribute"),
669 nullptr);
670 consumeToken(Token::floatliteral);
671 return builder.getFloatAttr(-val.getValue());
672 }
Chris Lattner7121b802018-07-04 20:45:39 -0700673
674 return (emitError("expected constant integer or floating point value"),
675 nullptr);
676 }
677
678 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700679 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700680 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700681 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700682 }
683
Chris Lattner85ee1512018-07-25 11:15:20 -0700684 case Token::l_square: {
685 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700686 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700687
688 auto parseElt = [&]() -> ParseResult {
689 elements.push_back(parseAttribute());
690 return elements.back() ? ParseSuccess : ParseFailure;
691 };
692
Chris Lattner85ee1512018-07-25 11:15:20 -0700693 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700694 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700695 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700696 }
James Molloyf0d2f442018-08-03 01:54:46 -0700697 case Token::hash_identifier:
698 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700699 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700700 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700701 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700702 return (emitError("expected constant attribute value"), nullptr);
703 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700704
705 case Token::at_identifier: {
706 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700707 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700708 consumeToken(Token::at_identifier);
709
710 if (parseToken(Token::colon, "expected ':' and function type"))
711 return nullptr;
712 auto typeLoc = getToken().getLoc();
713 Type *type = parseType();
714 if (!type)
715 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700716 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700717 if (!fnType)
718 return (emitError(typeLoc, "expected function type"), nullptr);
719
Chris Lattner1aa46322018-08-21 17:55:22 -0700720 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
721 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700722 }
723
James Molloyf0d2f442018-08-03 01:54:46 -0700724 default: {
725 if (Type *type = parseType())
726 return builder.getTypeAttr(type);
727 return nullptr;
728 }
729 }
Chris Lattner7121b802018-07-04 20:45:39 -0700730}
731
Chris Lattner7121b802018-07-04 20:45:39 -0700732/// Attribute dictionary.
733///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700734/// attribute-dict ::= `{` `}`
735/// | `{` attribute-entry (`,` attribute-entry)* `}`
736/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700737///
James Molloy0ff71542018-07-23 16:56:32 -0700738ParseResult
739Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700740 consumeToken(Token::l_brace);
741
742 auto parseElt = [&]() -> ParseResult {
743 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700744 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
745 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700746 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700747 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700748 consumeToken();
749
Chris Lattnerf7702a62018-07-23 17:30:01 -0700750 if (parseToken(Token::colon, "expected ':' in attribute list"))
751 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700752
753 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700754 if (!attr)
755 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700756
757 attributes.push_back({nameId, attr});
758 return ParseSuccess;
759 };
760
Chris Lattner40746442018-07-21 14:32:09 -0700761 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700762 return ParseFailure;
763
764 return ParseSuccess;
765}
766
767//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700768// Polyhedral structures.
769//===----------------------------------------------------------------------===//
770
Chris Lattner2e595eb2018-07-10 10:08:27 -0700771/// Lower precedence ops (all at the same precedence level). LNoOp is false in
772/// the boolean sense.
773enum AffineLowPrecOp {
774 /// Null value.
775 LNoOp,
776 Add,
777 Sub
778};
MLIR Teamf85a6262018-06-27 11:03:08 -0700779
Chris Lattner2e595eb2018-07-10 10:08:27 -0700780/// Higher precedence ops - all at the same precedence level. HNoOp is false in
781/// the boolean sense.
782enum AffineHighPrecOp {
783 /// Null value.
784 HNoOp,
785 Mul,
786 FloorDiv,
787 CeilDiv,
788 Mod
789};
Chris Lattner7121b802018-07-04 20:45:39 -0700790
Chris Lattner2e595eb2018-07-10 10:08:27 -0700791namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700792/// This is a specialized parser for affine structures (affine maps, affine
793/// expressions, and integer sets), maintaining the state transient to their
794/// bodies.
795class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700796public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700797 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700798
Chris Lattner2e595eb2018-07-10 10:08:27 -0700799 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700800 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700801
Chris Lattner2e595eb2018-07-10 10:08:27 -0700802private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700803 // Binary affine op parsing.
804 AffineLowPrecOp consumeIfLowPrecOp();
805 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700806
Chris Lattner2e595eb2018-07-10 10:08:27 -0700807 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700808 ParseResult parseDimIdList(unsigned &numDims);
809 ParseResult parseSymbolIdList(unsigned &numSymbols);
810 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700811
812 AffineExpr *parseAffineExpr();
813 AffineExpr *parseParentheticalExpr();
814 AffineExpr *parseNegateExpression(AffineExpr *lhs);
815 AffineExpr *parseIntegerExpr();
816 AffineExpr *parseBareIdExpr();
817
818 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700819 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700820 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
821 AffineExpr *rhs);
822 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
823 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
824 AffineLowPrecOp llhsOp);
825 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700826 AffineHighPrecOp llhsOp,
827 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700828 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700829
830private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700831 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700832};
833} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700834
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700835/// Create an affine binary high precedence op expression (mul's, div's, mod).
836/// opLoc is the location of the op token to be used to report errors
837/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700838AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
839 AffineExpr *lhs,
840 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700841 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700842 switch (op) {
843 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700844 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700845 emitError(opLoc, "non-affine expression: at least one of the multiply "
846 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700847 return nullptr;
848 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700849 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700850 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700851 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700852 emitError(opLoc, "non-affine expression: right operand of floordiv "
853 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700854 return nullptr;
855 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700856 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700857 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700858 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700859 emitError(opLoc, "non-affine expression: right operand of ceildiv "
860 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700861 return nullptr;
862 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700863 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700864 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700865 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700866 emitError(opLoc, "non-affine expression: right operand of mod "
867 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700868 return nullptr;
869 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700870 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700871 case HNoOp:
872 llvm_unreachable("can't create affine expression for null high prec op");
873 return nullptr;
874 }
875}
876
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700877/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700878AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
879 AffineExpr *lhs,
880 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700881 switch (op) {
882 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700883 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700884 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700885 return builder.getAddExpr(
886 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700887 case AffineLowPrecOp::LNoOp:
888 llvm_unreachable("can't create affine expression for null low prec op");
889 return nullptr;
890 }
891}
892
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700893/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700894/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700895AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700896 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700897 case Token::plus:
898 consumeToken(Token::plus);
899 return AffineLowPrecOp::Add;
900 case Token::minus:
901 consumeToken(Token::minus);
902 return AffineLowPrecOp::Sub;
903 default:
904 return AffineLowPrecOp::LNoOp;
905 }
906}
907
908/// Consume this token if it is a higher precedence affine op (there are only
909/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700910AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700911 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700912 case Token::star:
913 consumeToken(Token::star);
914 return Mul;
915 case Token::kw_floordiv:
916 consumeToken(Token::kw_floordiv);
917 return FloorDiv;
918 case Token::kw_ceildiv:
919 consumeToken(Token::kw_ceildiv);
920 return CeilDiv;
921 case Token::kw_mod:
922 consumeToken(Token::kw_mod);
923 return Mod;
924 default:
925 return HNoOp;
926 }
927}
928
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929/// Parse a high precedence op expression list: mul, div, and mod are high
930/// precedence binary ops, i.e., parse a
931/// expr_1 op_1 expr_2 op_2 ... expr_n
932/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
933/// All affine binary ops are left associative.
934/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
935/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700936/// null. llhsOpLoc is the location of the llhsOp token that will be used to
937/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700938AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
939 AffineHighPrecOp llhsOp,
940 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700941 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700942 if (!lhs)
943 return nullptr;
944
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700945 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700946 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700947 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700948 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700949 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700950 if (!expr)
951 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700952 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 }
954 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700955 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 }
957
958 // This is the last operand in this expression.
959 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700960 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961
962 // No llhs, 'lhs' itself is the expression.
963 return lhs;
964}
965
966/// Parse an affine expression inside parentheses.
967///
968/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700969AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700970 if (parseToken(Token::l_paren, "expected '('"))
971 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700972 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700973 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700974
Chris Lattner2e595eb2018-07-10 10:08:27 -0700975 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700978 if (parseToken(Token::r_paren, "expected ')'"))
979 return nullptr;
980
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700981 return expr;
982}
983
984/// Parse the negation expression.
985///
986/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700987AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700988 if (parseToken(Token::minus, "expected '-'"))
989 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700990
Chris Lattner2e595eb2018-07-10 10:08:27 -0700991 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700992 // Since negation has the highest precedence of all ops (including high
993 // precedence ops) but lower than parentheses, we are only going to use
994 // parseAffineOperandExpr instead of parseAffineExpr here.
995 if (!operand)
996 // Extra error message although parseAffineOperandExpr would have
997 // complained. Leads to a better diagnostic.
998 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700999 auto *minusOne = builder.getConstantExpr(-1);
1000 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001001}
1002
1003/// Parse a bare id that may appear in an affine expression.
1004///
1005/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -07001006AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001007 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001008 return (emitError("expected bare identifier"), nullptr);
1009
Chris Lattner48af7d12018-07-09 19:05:38 -07001010 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001011 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001012 if (entry.first == sRef) {
1013 consumeToken(Token::bare_identifier);
1014 return entry.second;
1015 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001016 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001017
1018 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001019}
1020
1021/// Parse a positive integral constant appearing in an affine expression.
1022///
1023/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001024AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001025 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001026 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001027 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001028
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001029 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001030 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001031}
1032
1033/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001034/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1035/// operator, the rhs of which is being parsed. This is used to determine
1036/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001037// Eg: for an expression without parentheses (like i + j + k + l), each
1038// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1039// operand expression, it's an op expression and will be parsed via
1040// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1041// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001042AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001043 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001044 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001045 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001046 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001047 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001048 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001049 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001050 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001051 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001052 case Token::kw_ceildiv:
1053 case Token::kw_floordiv:
1054 case Token::kw_mod:
1055 case Token::plus:
1056 case Token::star:
1057 if (lhs)
1058 emitError("missing right operand of binary operator");
1059 else
1060 emitError("missing left operand of binary operator");
1061 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001062 default:
1063 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001064 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001065 else
1066 emitError("expected affine expression");
1067 return nullptr;
1068 }
1069}
1070
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001071/// Parse affine expressions that are bare-id's, integer constants,
1072/// parenthetical affine expressions, and affine op expressions that are a
1073/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001074///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001075/// All binary op's associate from left to right.
1076///
1077/// {add, sub} have lower precedence than {mul, div, and mod}.
1078///
Uday Bondhugula76345202018-07-09 13:47:52 -07001079/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1080/// ceildiv, and mod are at the same higher precedence level. Negation has
1081/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001082///
1083/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001084/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1085/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1086/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001087/// associativity.
1088///
1089/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001090/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1091/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001092AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1093 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001094 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001096 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001097
1098 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001099 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001100 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001101 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001102 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001103 }
1104 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001105 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001106 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001107 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001108 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001109 // We have a higher precedence op here. Get the rhs operand for the llhs
1110 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001111 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001112 if (!highRes)
1113 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001114
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001115 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001116 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001117 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001118 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001119
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001120 // Recurse for subsequent low prec op's after the affine high prec op
1121 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001122 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1123 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001124 return expr;
1125 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001126 // Last operand in the expression list.
1127 if (llhs)
1128 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1129 // No llhs, 'lhs' itself is the expression.
1130 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001131}
1132
1133/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001134/// affine-expr ::= `(` affine-expr `)`
1135/// | `-` affine-expr
1136/// | affine-expr `+` affine-expr
1137/// | affine-expr `-` affine-expr
1138/// | affine-expr `*` affine-expr
1139/// | affine-expr `floordiv` affine-expr
1140/// | affine-expr `ceildiv` affine-expr
1141/// | affine-expr `mod` affine-expr
1142/// | bare-id
1143/// | integer-literal
1144///
1145/// Additional conditions are checked depending on the production. For eg., one
1146/// of the operands for `*` has to be either constant/symbolic; the second
1147/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001148AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001149 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001150}
1151
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001152/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001153/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001154/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001155ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001156 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001157 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001158
1159 auto name = getTokenSpelling();
1160 for (auto entry : dimsAndSymbols) {
1161 if (entry.first == name)
1162 return emitError("redefinition of identifier '" + Twine(name) + "'");
1163 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001164 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001165
1166 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001167 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001168}
1169
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001170/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001171ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001172 consumeToken(Token::l_square);
1173 auto parseElt = [&]() -> ParseResult {
1174 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1175 return parseIdentifierDefinition(symbol);
1176 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001177 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001178}
1179
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001180/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001181ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001182 if (parseToken(Token::l_paren,
1183 "expected '(' at start of dimensional identifiers list"))
1184 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001185
Chris Lattner413db6a2018-07-25 12:55:50 -07001186 auto parseElt = [&]() -> ParseResult {
1187 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1188 return parseIdentifierDefinition(dimension);
1189 };
Chris Lattner40746442018-07-21 14:32:09 -07001190 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001191}
1192
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001193/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001194///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001195/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1196/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1197/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001198///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001199/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001200AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001201 unsigned numDims = 0, numSymbols = 0;
1202
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001203 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001204 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001205 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001206
1207 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001208 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001209 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001210 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001211 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001212
1213 if (parseToken(Token::arrow, "expected '->' or '['") ||
1214 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001215 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001216
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001217 SmallVector<AffineExpr *, 4> exprs;
1218 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001219 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001220 ParseResult res = elt ? ParseSuccess : ParseFailure;
1221 exprs.push_back(elt);
1222 return res;
1223 };
1224
1225 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001226 // affine expressions); the list cannot be empty.
1227 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001228 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001229 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001230
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001231 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001232 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1233 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1234 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001235 // TODO: check if sizes are non-negative whenever they are constant.
1236 SmallVector<AffineExpr *, 4> rangeSizes;
1237 if (consumeIf(Token::kw_size)) {
1238 // Location of the l_paren token (if it exists) for error reporting later.
1239 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001240 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1241 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001242
1243 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001244 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001245 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001246 if (!elt)
1247 return ParseFailure;
1248
1249 if (!elt->isSymbolicOrConstant())
1250 return emitError(loc,
1251 "size expressions cannot refer to dimension values");
1252
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001253 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001254 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001255 };
1256
Chris Lattner40746442018-07-21 14:32:09 -07001257 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001258 return nullptr;
1259 if (exprs.size() > rangeSizes.size())
1260 return (emitError(loc, "fewer range sizes than range expressions"),
1261 nullptr);
1262 if (exprs.size() < rangeSizes.size())
1263 return (emitError(loc, "more range sizes than range expressions"),
1264 nullptr);
1265 }
1266
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001267 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001268 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001269}
1270
Chris Lattner2e595eb2018-07-10 10:08:27 -07001271AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001272 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001273}
1274
MLIR Team718c82f2018-07-16 09:45:22 -07001275AffineMap *Parser::parseAffineMapReference() {
1276 if (getToken().is(Token::hash_identifier)) {
1277 // Parse affine map identifier and verify that it exists.
1278 StringRef affineMapId = getTokenSpelling().drop_front();
1279 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1280 return (emitError("undefined affine map id '" + affineMapId + "'"),
1281 nullptr);
1282 consumeToken(Token::hash_identifier);
1283 return getState().affineMapDefinitions[affineMapId];
1284 }
1285 // Try to parse inline affine map.
1286 return parseAffineMapInline();
1287}
1288
MLIR Teamf85a6262018-06-27 11:03:08 -07001289//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001290// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001291//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001292
Chris Lattner7f9cc272018-07-19 08:35:28 -07001293namespace {
1294/// This class contains parser state that is common across CFG and ML functions,
1295/// notably for dealing with operations and SSA values.
1296class FunctionParser : public Parser {
1297public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001298 enum class Kind { CFGFunc, MLFunc };
1299
1300 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001301
Chris Lattner6119d382018-07-20 18:41:34 -07001302 /// After the function is finished parsing, this function checks to see if
1303 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001304 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001305
1306 /// This represents a use of an SSA value in the program. The first two
1307 /// entries in the tuple are the name and result number of a reference. The
1308 /// third is the location of the reference, which is used in case this ends up
1309 /// being a use of an undefined value.
1310 struct SSAUseInfo {
1311 StringRef name; // Value name, e.g. %42 or %abc
1312 unsigned number; // Number, specified with #12
1313 SMLoc loc; // Location of first definition or use.
1314 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001315
1316 /// Given a reference to an SSA value and its type, return a reference. This
1317 /// returns null on failure.
1318 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1319
1320 /// Register a definition of a value with the symbol table.
1321 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1322
1323 // SSA parsing productions.
1324 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001325 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001326
1327 template <typename ResultType>
1328 ResultType parseSSADefOrUseAndType(
1329 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1330
1331 SSAValue *parseSSAUseAndType() {
1332 return parseSSADefOrUseAndType<SSAValue *>(
1333 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1334 return resolveSSAUse(useInfo, type);
1335 });
1336 }
Chris Lattner40746442018-07-21 14:32:09 -07001337
1338 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001339 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001340 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1341 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001342
1343 // Operations
1344 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001345 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1346 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001347
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001348protected:
1349 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1350
Chris Lattner7f9cc272018-07-19 08:35:28 -07001351private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001352 /// Kind indicates if this is CFG or ML function parser.
1353 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001354 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001355 /// their name. This has one entry per result number.
1356 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1357
1358 /// These are all of the placeholders we've made along with the location of
1359 /// their first reference, to allow checking for use of undefined values.
1360 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1361
1362 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1363
1364 /// Return true if this is a forward reference.
1365 bool isForwardReferencePlaceholder(SSAValue *value) {
1366 return forwardReferencePlaceholders.count(value);
1367 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001368};
1369} // end anonymous namespace
1370
Chris Lattner6119d382018-07-20 18:41:34 -07001371/// Create and remember a new placeholder for a forward reference.
1372SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1373 Type *type) {
1374 // Forward references are always created as instructions, even in ML
1375 // functions, because we just need something with a def/use chain.
1376 //
1377 // We create these placeholders as having an empty name, which we know cannot
1378 // be created through normal user input, allowing us to distinguish them.
1379 auto name = Identifier::get("placeholder", getContext());
Chris Lattnerfc647d52018-08-27 21:05:16 -07001380 auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
1381 /*operands=*/{}, type,
1382 /*attributes=*/{}, getContext());
Chris Lattner6119d382018-07-20 18:41:34 -07001383 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1384 return inst->getResult(0);
1385}
1386
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001387/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001388/// it specifies. This returns null on failure.
1389SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001390 auto &entries = values[useInfo.name];
1391
Chris Lattner7f9cc272018-07-19 08:35:28 -07001392 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001393 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1394 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001395 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001396 if (result->getType() == type)
1397 return result;
1398
Chris Lattner6119d382018-07-20 18:41:34 -07001399 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1400 "' expects different type than prior uses");
1401 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001402 return nullptr;
1403 }
1404
Chris Lattner6119d382018-07-20 18:41:34 -07001405 // Make sure we have enough slots for this.
1406 if (entries.size() <= useInfo.number)
1407 entries.resize(useInfo.number + 1);
1408
1409 // If the value has already been defined and this is an overly large result
1410 // number, diagnose that.
1411 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1412 return (emitError(useInfo.loc, "reference to invalid result number"),
1413 nullptr);
1414
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001415 // Otherwise, this is a forward reference. If we are in ML function return
1416 // an error. In CFG function, create a placeholder and remember
1417 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001418 if (getKind() == Kind::MLFunc)
1419 return (
1420 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1421 nullptr);
1422
Chris Lattner6119d382018-07-20 18:41:34 -07001423 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1424 entries[useInfo.number].first = result;
1425 entries[useInfo.number].second = useInfo.loc;
1426 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001427}
1428
1429/// Register a definition of a value with the symbol table.
1430ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001431 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001432
Chris Lattner6119d382018-07-20 18:41:34 -07001433 // Make sure there is a slot for this value.
1434 if (entries.size() <= useInfo.number)
1435 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001436
Chris Lattner6119d382018-07-20 18:41:34 -07001437 // If we already have an entry for this, check to see if it was a definition
1438 // or a forward reference.
1439 if (auto *existing = entries[useInfo.number].first) {
1440 if (!isForwardReferencePlaceholder(existing)) {
1441 emitError(useInfo.loc,
1442 "redefinition of SSA value '" + useInfo.name + "'");
1443 return emitError(entries[useInfo.number].second,
1444 "previously defined here");
1445 }
1446
1447 // If it was a forward reference, update everything that used it to use the
1448 // actual definition instead, delete the forward ref, and remove it from our
1449 // set of forward references we track.
1450 existing->replaceAllUsesWith(value);
1451 existing->getDefiningInst()->destroy();
1452 forwardReferencePlaceholders.erase(existing);
1453 }
1454
1455 entries[useInfo.number].first = value;
1456 entries[useInfo.number].second = useInfo.loc;
1457 return ParseSuccess;
1458}
1459
1460/// After the function is finished parsing, this function checks to see if
1461/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001462ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001463 // Check for any forward references that are left. If we find any, error out.
1464 if (!forwardReferencePlaceholders.empty()) {
1465 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1466 // Iteration over the map isn't determinstic, so sort by source location.
1467 for (auto entry : forwardReferencePlaceholders)
1468 errors.push_back({entry.second.getPointer(), entry.first});
1469 llvm::array_pod_sort(errors.begin(), errors.end());
1470
1471 for (auto entry : errors)
1472 emitError(SMLoc::getFromPointer(entry.first),
1473 "use of undeclared SSA value name");
1474 return ParseFailure;
1475 }
1476
1477 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001478}
1479
Chris Lattner78276e32018-07-07 15:48:26 -07001480/// Parse a SSA operand for an instruction or statement.
1481///
James Molloy61a656c2018-07-22 15:45:24 -07001482/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001483///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001484ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001485 result.name = getTokenSpelling();
1486 result.number = 0;
1487 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001488 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1489 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001490
1491 // If we have an affine map ID, it is a result number.
1492 if (getToken().is(Token::hash_identifier)) {
1493 if (auto value = getToken().getHashIdentifierNumber())
1494 result.number = value.getValue();
1495 else
1496 return emitError("invalid SSA value result number");
1497 consumeToken(Token::hash_identifier);
1498 }
1499
Chris Lattner7f9cc272018-07-19 08:35:28 -07001500 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001501}
1502
1503/// Parse a (possibly empty) list of SSA operands.
1504///
1505/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1506/// ssa-use-list-opt ::= ssa-use-list?
1507///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001508ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001509FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001510 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001511 return ParseSuccess;
1512 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001513 SSAUseInfo result;
1514 if (parseSSAUse(result))
1515 return ParseFailure;
1516 results.push_back(result);
1517 return ParseSuccess;
1518 });
Chris Lattner78276e32018-07-07 15:48:26 -07001519}
1520
1521/// Parse an SSA use with an associated type.
1522///
1523/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001524template <typename ResultType>
1525ResultType FunctionParser::parseSSADefOrUseAndType(
1526 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001527
Chris Lattnerf7702a62018-07-23 17:30:01 -07001528 SSAUseInfo useInfo;
1529 if (parseSSAUse(useInfo) ||
1530 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1531 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001532
Chris Lattner7f9cc272018-07-19 08:35:28 -07001533 auto *type = parseType();
1534 if (!type)
1535 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001536
James Molloy61a656c2018-07-22 15:45:24 -07001537 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001538}
1539
Chris Lattner2c402672018-07-23 11:56:17 -07001540/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1541/// followed by a type list. If hasParens is true, then the operands are
1542/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001543///
Chris Lattner2c402672018-07-23 11:56:17 -07001544/// ssa-use-and-type-list[parens]
1545/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1546///
1547/// ssa-use-and-type-list[!parens]
1548/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001549///
Chris Lattner40746442018-07-21 14:32:09 -07001550template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001551ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001552 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1553
1554 // If we are in the parenthesized form and no paren exists, then we succeed
1555 // with an empty list.
1556 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001557 return ParseSuccess;
1558
Chris Lattner2c402672018-07-23 11:56:17 -07001559 SmallVector<SSAUseInfo, 4> valueIDs;
1560 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001561 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001562
1563 if (isParenthesized && !consumeIf(Token::r_paren))
1564 return emitError("expected ')' in operand list");
1565
1566 // If there were no operands, then there is no colon or type lists.
1567 if (valueIDs.empty())
1568 return ParseSuccess;
1569
Chris Lattner2c402672018-07-23 11:56:17 -07001570 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001571 if (parseToken(Token::colon, "expected ':' in operand list") ||
1572 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001573 return ParseFailure;
1574
1575 if (valueIDs.size() != types.size())
1576 return emitError("expected " + Twine(valueIDs.size()) +
1577 " types to match operand list");
1578
1579 results.reserve(valueIDs.size());
1580 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1581 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1582 results.push_back(cast<ValueTy>(value));
1583 else
1584 return ParseFailure;
1585 }
1586
1587 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001588}
1589
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001590/// Parse the CFG or MLFunc operation.
1591///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001592/// operation ::=
1593/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1594/// `:` function-type
1595///
1596ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001597FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001598 auto loc = getToken().getLoc();
1599
1600 StringRef resultID;
1601 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001602 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001603 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001604 if (parseToken(Token::equal, "expected '=' after SSA name"))
1605 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001606 }
1607
Chris Lattner85ee1512018-07-25 11:15:20 -07001608 Operation *op;
1609 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1610 op = parseCustomOperation(createOpFunc);
1611 else if (getToken().is(Token::string))
1612 op = parseVerboseOperation(createOpFunc);
1613 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001614 return emitError("expected operation name in quotes");
1615
Chris Lattner85ee1512018-07-25 11:15:20 -07001616 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001617 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001618 return ParseFailure;
1619
1620 // We just parsed an operation. If it is a recognized one, verify that it
1621 // is structurally as we expect. If not, produce an error with a reasonable
1622 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001623 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001624 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001625 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001626 }
1627
Chris Lattner7f9cc272018-07-19 08:35:28 -07001628 // If the instruction had a name, register it.
1629 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001630 if (op->getNumResults() == 0)
1631 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001632
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001633 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001634 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1635 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001636 }
1637
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001638 return ParseSuccess;
1639}
Chris Lattnere79379a2018-06-22 10:39:19 -07001640
Chris Lattner85ee1512018-07-25 11:15:20 -07001641Operation *FunctionParser::parseVerboseOperation(
1642 const CreateOperationFunction &createOpFunc) {
Chris Lattner1628fa02018-08-23 14:32:25 -07001643
1644 // Get location information for the operation.
1645 auto *srcLocation = getEncodedSourceLocation(getToken().getLoc());
1646
Chris Lattner85ee1512018-07-25 11:15:20 -07001647 auto name = getToken().getStringValue();
1648 if (name.empty())
1649 return (emitError("empty operation name is invalid"), nullptr);
1650
1651 consumeToken(Token::string);
1652
Chris Lattner1628fa02018-08-23 14:32:25 -07001653 OperationState result(builder.getContext(), srcLocation, name);
Chris Lattner992a1272018-08-07 12:02:37 -07001654
Chris Lattner85ee1512018-07-25 11:15:20 -07001655 // Parse the operand list.
1656 SmallVector<SSAUseInfo, 8> operandInfos;
1657
1658 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1659 parseOptionalSSAUseList(operandInfos) ||
1660 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1661 return nullptr;
1662 }
1663
Chris Lattner85ee1512018-07-25 11:15:20 -07001664 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001665 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001666 return nullptr;
1667 }
1668
1669 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1670 return nullptr;
1671
1672 auto typeLoc = getToken().getLoc();
1673 auto type = parseType();
1674 if (!type)
1675 return nullptr;
1676 auto fnType = dyn_cast<FunctionType>(type);
1677 if (!fnType)
1678 return (emitError(typeLoc, "expected function type"), nullptr);
1679
Chris Lattner1eb77482018-08-22 19:25:49 -07001680 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001681
Chris Lattner85ee1512018-07-25 11:15:20 -07001682 // Check that we have the right number of types for the operands.
1683 auto operandTypes = fnType->getInputs();
1684 if (operandTypes.size() != operandInfos.size()) {
1685 auto plural = "s"[operandInfos.size() == 1];
1686 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1687 " operand type" + plural + " but had " +
1688 llvm::utostr(operandTypes.size())),
1689 nullptr);
1690 }
1691
1692 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001693 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001694 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1695 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001696 return nullptr;
1697 }
1698
Chris Lattner992a1272018-08-07 12:02:37 -07001699 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001700}
1701
1702namespace {
1703class CustomOpAsmParser : public OpAsmParser {
1704public:
1705 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1706 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1707
Chris Lattner85ee1512018-07-25 11:15:20 -07001708 //===--------------------------------------------------------------------===//
1709 // High level parsing methods.
1710 //===--------------------------------------------------------------------===//
1711
Chris Lattner1aa46322018-08-21 17:55:22 -07001712 bool getCurrentLocation(llvm::SMLoc *loc) override {
1713 *loc = parser.getToken().getLoc();
1714 return false;
1715 }
Chris Lattner091a6b52018-08-23 14:58:27 -07001716 bool parseComma() override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001717 return parser.parseToken(Token::comma, "expected ','");
1718 }
1719
Chris Lattner091a6b52018-08-23 14:58:27 -07001720 bool parseColonType(Type *&result) override {
1721 return parser.parseToken(Token::colon, "expected ':'") ||
1722 !(result = parser.parseType());
Chris Lattner85ee1512018-07-25 11:15:20 -07001723 }
1724
Chris Lattner091a6b52018-08-23 14:58:27 -07001725 bool parseColonTypeList(SmallVectorImpl<Type *> &result) override {
1726 if (parser.parseToken(Token::colon, "expected ':'"))
Chris Lattner85ee1512018-07-25 11:15:20 -07001727 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,
Chris Lattner091a6b52018-08-23 14:58:27 -07001743 SmallVectorImpl<NamedAttribute> &attrs) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001744 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001745 if (!result)
1746 return true;
1747
1748 attrs.push_back(
1749 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1750 return false;
1751 }
1752
1753 /// If a named attribute list is present, parse is into result.
Chris Lattner091a6b52018-08-23 14:58:27 -07001754 bool
1755 parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result) override {
Chris Lattner85cf26d2018-08-02 16:54:36 -07001756 if (parser.getToken().isNot(Token::l_brace))
1757 return false;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001758 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001759 }
1760
Chris Lattner1aa46322018-08-21 17:55:22 -07001761 /// Parse a function name like '@foo' and return the name in a form that can
1762 /// be passed to resolveFunctionName when a function type is available.
1763 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1764 loc = parser.getToken().getLoc();
1765
1766 if (parser.getToken().isNot(Token::at_identifier))
1767 return emitError(loc, "expected function name");
1768
1769 result = parser.getTokenSpelling();
1770 parser.consumeToken(Token::at_identifier);
1771 return false;
1772 }
1773
Chris Lattner85ee1512018-07-25 11:15:20 -07001774 bool parseOperand(OperandType &result) override {
1775 FunctionParser::SSAUseInfo useInfo;
1776 if (parser.parseSSAUse(useInfo))
1777 return true;
1778
1779 result = {useInfo.loc, useInfo.name, useInfo.number};
1780 return false;
1781 }
1782
1783 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1784 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001785 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001786 auto startLoc = parser.getToken().getLoc();
1787
Chris Lattner85cf26d2018-08-02 16:54:36 -07001788 // Handle delimiters.
1789 switch (delimiter) {
1790 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001791 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001792 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001793 if (parser.getToken().isNot(Token::l_paren))
1794 return false;
1795 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001796 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001797 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1798 return true;
1799 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001800 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001801 if (parser.getToken().isNot(Token::l_square))
1802 return false;
1803 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001804 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001805 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1806 return true;
1807 break;
1808 }
1809
1810 // Check for zero operands.
1811 if (parser.getToken().is(Token::percent_identifier)) {
1812 do {
1813 OperandType operand;
1814 if (parseOperand(operand))
1815 return true;
1816 result.push_back(operand);
1817 } while (parser.consumeIf(Token::comma));
1818 }
1819
Chris Lattner85cf26d2018-08-02 16:54:36 -07001820 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001821 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001822 switch (delimiter) {
1823 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001824 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001825 case Delimiter::OptionalParen:
1826 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001827 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1828 return true;
1829 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001830 case Delimiter::OptionalSquare:
1831 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001832 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1833 return true;
1834 break;
1835 }
1836
1837 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1838 emitError(startLoc,
1839 "expected " + Twine(requiredOperandCount) + " operands");
1840 return false;
1841 }
1842
Chris Lattner1aa46322018-08-21 17:55:22 -07001843 /// Resolve a parse function name and a type into a function reference.
1844 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1845 llvm::SMLoc loc, Function *&result) {
1846 result = parser.resolveFunctionReference(name, loc, type);
1847 return result == nullptr;
1848 }
1849
Chris Lattner85ee1512018-07-25 11:15:20 -07001850 //===--------------------------------------------------------------------===//
1851 // Methods for interacting with the parser
1852 //===--------------------------------------------------------------------===//
1853
1854 Builder &getBuilder() const override { return parser.builder; }
1855
1856 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1857
Chris Lattner1aa46322018-08-21 17:55:22 -07001858 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001859 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001860 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1861 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001862 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1863 result.push_back(value);
1864 return false;
1865 }
1866 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001867 }
1868
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001869 /// Emit a diagnostic at the specified location and return true.
1870 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001871 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1872 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001873 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001874 }
1875
1876 bool didEmitError() const { return emittedError; }
1877
1878private:
1879 SMLoc nameLoc;
1880 StringRef opName;
1881 FunctionParser &parser;
1882 bool emittedError = false;
1883};
1884} // end anonymous namespace.
1885
1886Operation *FunctionParser::parseCustomOperation(
1887 const CreateOperationFunction &createOpFunc) {
1888 auto opLoc = getToken().getLoc();
1889 auto opName = getTokenSpelling();
1890 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1891
1892 auto *opDefinition = getOperationSet().lookup(opName);
1893 if (!opDefinition) {
1894 opAsmParser.emitError(opLoc, "is unknown");
1895 return nullptr;
1896 }
1897
1898 consumeToken();
1899
Chris Lattner1aa46322018-08-21 17:55:22 -07001900 // If the custom op parser crashes, produce some indication to help debugging.
1901 std::string opNameStr = opName.str();
1902 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1903 opNameStr.c_str());
1904
Chris Lattner1628fa02018-08-23 14:32:25 -07001905 // Get location information for the operation.
1906 auto *srcLocation = getEncodedSourceLocation(opLoc);
1907
Chris Lattner85ee1512018-07-25 11:15:20 -07001908 // Have the op implementation take a crack and parsing this.
Chris Lattner1628fa02018-08-23 14:32:25 -07001909 OperationState opState(builder.getContext(), srcLocation, opName);
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001910 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1911 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001912
1913 // If it emitted an error, we failed.
1914 if (opAsmParser.didEmitError())
1915 return nullptr;
1916
1917 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001918 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001919}
1920
Chris Lattner48af7d12018-07-09 19:05:38 -07001921//===----------------------------------------------------------------------===//
1922// CFG Functions
1923//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001924
Chris Lattner4c95a502018-06-23 16:03:42 -07001925namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001926/// This is a specialized parser for CFGFunction's, maintaining the state
1927/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001928class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001929public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001930 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001931 : FunctionParser(state, Kind::CFGFunc), function(function),
1932 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001933
1934 ParseResult parseFunctionBody();
1935
1936private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001937 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001938 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001939
1940 /// This builder intentionally shadows the builder in the base class, with a
1941 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001942 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001943
Chris Lattner4c95a502018-06-23 16:03:42 -07001944 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001945 /// already exist. The location specified is the point of use, which allows
1946 /// us to diagnose references to blocks that are not defined precisely.
1947 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1948 auto &blockAndLoc = blocksByName[name];
1949 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001950 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001951 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001952 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001953 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001954 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001955
James Molloy61a656c2018-07-22 15:45:24 -07001956 ParseResult
1957 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1958 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001959 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1960 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001961
Chris Lattner48af7d12018-07-09 19:05:38 -07001962 ParseResult parseBasicBlock();
Chris Lattner48af7d12018-07-09 19:05:38 -07001963 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001964};
1965} // end anonymous namespace
1966
James Molloy61a656c2018-07-22 15:45:24 -07001967/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001968/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001969///
1970/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1971///
1972ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1973 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1974 if (getToken().is(Token::r_brace))
1975 return ParseSuccess;
1976
1977 return parseCommaSeparatedList([&]() -> ParseResult {
1978 auto type = parseSSADefOrUseAndType<Type *>(
1979 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1980 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001981 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001982 return nullptr;
1983 return type;
1984 });
1985 return type ? ParseSuccess : ParseFailure;
1986 });
1987}
1988
Chris Lattner48af7d12018-07-09 19:05:38 -07001989ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001990 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001991 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1992 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001993
1994 // Make sure we have at least one block.
1995 if (getToken().is(Token::r_brace))
1996 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001997
1998 // Parse the list of blocks.
1999 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07002000 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07002001 return ParseFailure;
2002
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002003 // Verify that all referenced blocks were defined. Iteration over a
2004 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002005 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002006 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002007 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002008 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002009 "reference to an undefined basic block '" + elt.first() +
2010 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002011 }
2012
Chris Lattner40746442018-07-21 14:32:09 -07002013 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002014}
2015
2016/// Basic block declaration.
2017///
2018/// basic-block ::= bb-label instruction* terminator-stmt
2019/// bb-label ::= bb-id bb-arg-list? `:`
2020/// bb-id ::= bare-id
2021/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2022///
Chris Lattner48af7d12018-07-09 19:05:38 -07002023ParseResult CFGFunctionParser::parseBasicBlock() {
2024 SMLoc nameLoc = getToken().getLoc();
2025 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002026 if (parseToken(Token::bare_identifier, "expected basic block name"))
2027 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002028
Chris Lattner48af7d12018-07-09 19:05:38 -07002029 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002030
2031 // If this block has already been parsed, then this is a redefinition with the
2032 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002033 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002034 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2035
Chris Lattner78276e32018-07-07 15:48:26 -07002036 // If an argument list is present, parse it.
2037 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002038 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002039 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2040 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002041 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002042 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002043
James Molloy61a656c2018-07-22 15:45:24 -07002044 // Add the block to the function.
2045 function->push_back(block);
2046
Chris Lattnerf7702a62018-07-23 17:30:01 -07002047 if (parseToken(Token::colon, "expected ':' after basic block name"))
2048 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002049
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002050 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002051 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002052
Chris Lattner992a1272018-08-07 12:02:37 -07002053 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2054 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002055 };
2056
Chris Lattnered65a732018-06-28 20:45:33 -07002057 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002058 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002059 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002060 return ParseFailure;
2061 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002062
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002063 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002064 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002065
2066 return ParseSuccess;
2067}
2068
James Molloy4f788372018-07-24 15:01:27 -07002069ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2070 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2071 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2072 if (parseToken(Token::bare_identifier, "expected basic block name"))
2073 return ParseFailure;
2074
2075 if (!consumeIf(Token::l_paren))
2076 return ParseSuccess;
2077 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2078 parseToken(Token::r_paren, "expected ')' to close argument list"))
2079 return ParseFailure;
2080 return ParseSuccess;
2081}
2082
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002083/// Parse the terminator instruction for a basic block.
2084///
2085/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002086/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002087/// terminator-stmt ::=
2088/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2089/// terminator-stmt ::= `return` ssa-use-and-type-list?
2090///
Chris Lattner48af7d12018-07-09 19:05:38 -07002091TerminatorInst *CFGFunctionParser::parseTerminator() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002092 auto loc = getToken().getLoc();
2093
Chris Lattner48af7d12018-07-09 19:05:38 -07002094 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002095 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002096 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002097
Chris Lattner40746442018-07-21 14:32:09 -07002098 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002099 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002100
Chris Lattner2c402672018-07-23 11:56:17 -07002101 // Parse any operands.
2102 SmallVector<CFGValue *, 8> operands;
2103 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2104 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002105 return builder.createReturn(getEncodedSourceLocation(loc), operands);
Chris Lattner40746442018-07-21 14:32:09 -07002106 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002107
2108 case Token::kw_br: {
2109 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002110 BasicBlock *destBB;
2111 SmallVector<CFGValue *, 4> values;
2112 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002113 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002114 auto branch = builder.createBranch(getEncodedSourceLocation(loc), destBB);
James Molloy4f788372018-07-24 15:01:27 -07002115 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002116 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002117 }
James Molloy4f788372018-07-24 15:01:27 -07002118
2119 case Token::kw_cond_br: {
2120 consumeToken(Token::kw_cond_br);
2121 SSAUseInfo ssaUse;
2122 if (parseSSAUse(ssaUse))
2123 return nullptr;
2124 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2125 if (!cond)
2126 return (emitError("expected type was boolean (i1)"), nullptr);
2127 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2128 return nullptr;
2129
2130 BasicBlock *trueBlock;
2131 SmallVector<CFGValue *, 4> trueOperands;
2132 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2133 return nullptr;
2134
2135 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2136 return nullptr;
2137
2138 BasicBlock *falseBlock;
2139 SmallVector<CFGValue *, 4> falseOperands;
2140 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2141 return nullptr;
2142
Chris Lattner091a6b52018-08-23 14:58:27 -07002143 auto branch =
2144 builder.createCondBranch(getEncodedSourceLocation(loc),
2145 cast<CFGValue>(cond), trueBlock, falseBlock);
James Molloy4f788372018-07-24 15:01:27 -07002146 branch->addTrueOperands(trueOperands);
2147 branch->addFalseOperands(falseOperands);
2148 return branch;
2149 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002150 }
2151}
2152
Chris Lattner48af7d12018-07-09 19:05:38 -07002153//===----------------------------------------------------------------------===//
2154// ML Functions
2155//===----------------------------------------------------------------------===//
2156
2157namespace {
2158/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002159class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002160public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002161 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002162 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002163 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002164
2165 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002166
2167private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002168 MLFunction *function;
2169
2170 /// This builder intentionally shadows the builder in the base class, with a
2171 /// more specific builder type.
2172 MLFuncBuilder builder;
2173
2174 ParseResult parseForStmt();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002175 ParseResult parseIntConstant(int64_t &val);
2176 ParseResult parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002177 unsigned numDims, unsigned numOperands,
2178 const char *affineStructName);
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002179 ParseResult parseBound(SmallVectorImpl<MLValue *> &operands, AffineMap *&map,
2180 bool isLower);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002181 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002182 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002183 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002184 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002185};
2186} // end anonymous namespace
2187
Chris Lattner48af7d12018-07-09 19:05:38 -07002188ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002189 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002190
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002191 // Parse statements in this function.
2192 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002193 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002194
Chris Lattner40746442018-07-21 14:32:09 -07002195 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002196}
2197
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002198/// For statement.
2199///
Chris Lattner48af7d12018-07-09 19:05:38 -07002200/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2201/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002202///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002203ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002204 consumeToken(Token::kw_for);
2205
Uday Bondhugula67701712018-08-21 16:01:23 -07002206 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002207 if (getToken().isNot(Token::percent_identifier))
2208 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002209
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002210 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002211 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002212 consumeToken(Token::percent_identifier);
2213
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002214 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002215 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002216
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002217 // Parse lower bound.
2218 SmallVector<MLValue *, 4> lbOperands;
2219 AffineMap *lbMap = nullptr;
2220 if (parseBound(lbOperands, lbMap, /*isLower*/ true))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002221 return ParseFailure;
2222
Chris Lattnerf7702a62018-07-23 17:30:01 -07002223 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2224 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002225
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002226 // Parse upper bound.
2227 SmallVector<MLValue *, 4> ubOperands;
2228 AffineMap *ubMap = nullptr;
2229 if (parseBound(ubOperands, ubMap, /*isLower*/ false))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002230 return ParseFailure;
2231
Uday Bondhugula67701712018-08-21 16:01:23 -07002232 // Parse step.
2233 int64_t step = 1;
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002234 if (consumeIf(Token::kw_step) && parseIntConstant(step))
2235 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002236
2237 // Create for statement.
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002238 ForStmt *forStmt =
2239 builder.createFor(getEncodedSourceLocation(loc), lbOperands, lbMap,
2240 ubOperands, ubMap, step);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002241
2242 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002243 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2244 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002245
2246 // If parsing of the for statement body fails,
2247 // MLIR contains for statement with those nested statements that have been
2248 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002249 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002250 return ParseFailure;
2251
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002252 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002253 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002254
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002255 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002256}
2257
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002258/// Parse integer constant as affine constant expression.
2259ParseResult MLFunctionParser::parseIntConstant(int64_t &val) {
2260 bool negate = consumeIf(Token::minus);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002261
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002262 if (getToken().isNot(Token::integer))
2263 return emitError("expected integer");
2264
2265 auto uval = getToken().getUInt64IntegerValue();
2266
2267 if (!uval.hasValue() || (int64_t)uval.getValue() < 0) {
2268 return emitError("bound or step is too large for affineint");
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002269 }
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002270
2271 val = (int64_t)uval.getValue();
2272 if (negate)
2273 val = -val;
2274 consumeToken();
2275
2276 return ParseSuccess;
2277}
2278
2279/// Dimensions and symbol use list.
2280///
2281/// dim-use-list ::= `(` ssa-use-list? `)`
2282/// symbol-use-list ::= `[` ssa-use-list? `]`
2283/// dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
2284///
2285ParseResult
2286MLFunctionParser::parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002287 unsigned numDims, unsigned numOperands,
2288 const char *affineStructName) {
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002289 if (parseToken(Token::l_paren, "expected '('"))
2290 return ParseFailure;
2291
2292 SmallVector<SSAUseInfo, 4> opInfo;
2293 parseOptionalSSAUseList(opInfo);
2294
2295 if (parseToken(Token::r_paren, "expected ')'"))
2296 return ParseFailure;
2297
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002298 if (numDims != opInfo.size())
2299 return emitError("dim operand count and " + Twine(affineStructName) +
2300 " dim count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002301
2302 if (consumeIf(Token::l_square)) {
2303 parseOptionalSSAUseList(opInfo);
2304 if (parseToken(Token::r_square, "expected ']'"))
2305 return ParseFailure;
2306 }
2307
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002308 if (numOperands != opInfo.size())
2309 return emitError("symbol operand count and " + Twine(affineStructName) +
2310 " symbol count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002311
2312 // Resolve SSA uses.
2313 Type *affineIntType = builder.getAffineIntType();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002314 for (unsigned i = 0, e = opInfo.size(); i != e; ++i) {
2315 SSAValue *sval = resolveSSAUse(opInfo[i], affineIntType);
2316 if (!sval)
2317 return ParseFailure;
2318
2319 auto *v = cast<MLValue>(sval);
2320 if (i < numDims && !v->isValidDim())
2321 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002322 "' cannot be used as a dimension id");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002323 if (i >= numDims && !v->isValidSymbol())
2324 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002325 "' cannot be used as a symbol");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002326 operands.push_back(v);
2327 }
2328
2329 return ParseSuccess;
2330}
2331
2332// Loop bound.
2333///
2334/// lower-bound ::= `max`? affine-map dim-and-symbol-use-list | shorthand-bound
2335/// upper-bound ::= `min`? affine-map dim-and-symbol-use-list | shorthand-bound
2336/// shorthand-bound ::= ssa-id | `-`? integer-literal
2337///
2338ParseResult MLFunctionParser::parseBound(SmallVectorImpl<MLValue *> &operands,
2339 AffineMap *&map, bool isLower) {
2340 // 'min' / 'max' prefixes are syntactic sugar. Ignore them.
2341 if (isLower)
2342 consumeIf(Token::kw_max);
2343 else
2344 consumeIf(Token::kw_min);
2345
2346 // Parse full form - affine map followed by dim and symbol list.
2347 if (getToken().isAny(Token::hash_identifier, Token::l_paren)) {
2348 map = parseAffineMapReference();
2349 if (!map)
2350 return ParseFailure;
2351
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002352 if (parseDimAndSymbolList(operands, map->getNumDims(),
2353 map->getNumOperands(), "affine map"))
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002354 return ParseFailure;
2355 return ParseSuccess;
2356 }
2357
2358 // Parse shorthand form.
2359 if (getToken().isAny(Token::minus, Token::integer)) {
2360 int64_t val;
2361 if (!parseIntConstant(val)) {
2362 map = builder.getConstantMap(val);
2363 return ParseSuccess;
2364 }
2365 return ParseFailure;
2366 }
2367
2368 // Parse ssa-id as identity map.
2369 SSAUseInfo opInfo;
2370 if (parseSSAUse(opInfo))
2371 return ParseFailure;
2372
2373 // TODO: improve error message when SSA value is not an affine integer.
2374 // Currently it is 'use of value ... expects different type than prior uses'
2375 if (auto *value = resolveSSAUse(opInfo, builder.getAffineIntType()))
2376 operands.push_back(cast<MLValue>(value));
2377 else
2378 return ParseFailure;
2379
2380 // Create an identity map using dim id for an induction variable and
2381 // symbol otherwise. This representation is optimized for storage.
2382 // Analysis passes may expand it into a multi-dimensional map if desired.
2383 if (isa<ForStmt>(operands[0]))
2384 map = builder.getDimIdentityMap();
2385 else
2386 map = builder.getSymbolIdentityMap();
2387
2388 return ParseSuccess;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002389}
2390
Uday Bondhugulabc535622018-08-07 14:24:38 -07002391/// Parse an affine constraint.
2392/// affine-constraint ::= affine-expr `>=` `0`
2393/// | affine-expr `==` `0`
2394///
2395/// isEq is set to true if the parsed constraint is an equality, false if it is
2396/// an inequality (greater than or equal).
2397///
2398AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2399 AffineExpr *expr = parseAffineExpr();
2400 if (!expr)
2401 return nullptr;
2402
2403 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2404 getToken().is(Token::integer)) {
2405 auto dim = getToken().getUnsignedIntegerValue();
2406 if (dim.hasValue() && dim.getValue() == 0) {
2407 consumeToken(Token::integer);
2408 *isEq = false;
2409 return expr;
2410 }
2411 return (emitError("expected '0' after '>='"), nullptr);
2412 }
2413
2414 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2415 getToken().is(Token::integer)) {
2416 auto dim = getToken().getUnsignedIntegerValue();
2417 if (dim.hasValue() && dim.getValue() == 0) {
2418 consumeToken(Token::integer);
2419 *isEq = true;
2420 return expr;
2421 }
2422 return (emitError("expected '0' after '=='"), nullptr);
2423 }
2424
2425 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2426 nullptr);
2427}
2428
2429/// Parse an integer set definition.
2430/// integer-set-inline
2431/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2432/// affine-constraint-conjunction ::= /*empty*/
2433/// | affine-constraint (`,` affine-constraint)*
2434///
2435IntegerSet *AffineParser::parseIntegerSetInline() {
2436 unsigned numDims = 0, numSymbols = 0;
2437
2438 // List of dimensional identifiers.
2439 if (parseDimIdList(numDims))
2440 return nullptr;
2441
2442 // Symbols are optional.
2443 if (getToken().is(Token::l_square)) {
2444 if (parseSymbolIdList(numSymbols))
2445 return nullptr;
2446 }
2447
2448 if (parseToken(Token::colon, "expected ':' or '['") ||
2449 parseToken(Token::l_paren,
2450 "expected '(' at start of integer set constraint list"))
2451 return nullptr;
2452
2453 SmallVector<AffineExpr *, 4> constraints;
2454 SmallVector<bool, 4> isEqs;
2455 auto parseElt = [&]() -> ParseResult {
2456 bool isEq;
2457 auto *elt = parseAffineConstraint(&isEq);
2458 ParseResult res = elt ? ParseSuccess : ParseFailure;
2459 if (elt) {
2460 constraints.push_back(elt);
2461 isEqs.push_back(isEq);
2462 }
2463 return res;
2464 };
2465
2466 // Parse a list of affine constraints (comma-separated) .
2467 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2468 // affine-constraint)* `)
2469 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2470 return nullptr;
2471
2472 // Parsed a valid integer set.
2473 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2474}
2475
2476IntegerSet *Parser::parseIntegerSetInline() {
2477 return AffineParser(state).parseIntegerSetInline();
2478}
2479
2480/// Parse a reference to an integer set.
2481/// integer-set ::= integer-set-id | integer-set-inline
2482/// integer-set-id ::= `@@` suffix-id
2483///
2484IntegerSet *Parser::parseIntegerSetReference() {
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002485 // TODO: change '@@' integer set prefix to '#'.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002486 if (getToken().is(Token::double_at_identifier)) {
2487 // Parse integer set identifier and verify that it exists.
2488 StringRef integerSetId = getTokenSpelling().drop_front(2);
2489 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2490 return (emitError("undefined integer set id '" + integerSetId + "'"),
2491 nullptr);
2492 consumeToken(Token::double_at_identifier);
2493 return getState().integerSetDefinitions[integerSetId];
2494 }
2495 // Try to parse an inline integer set definition.
2496 return parseIntegerSetInline();
2497}
2498
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002499/// If statement.
2500///
Chris Lattner48af7d12018-07-09 19:05:38 -07002501/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2502/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2503/// ml-if-stmt ::= ml-if-head
2504/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002505///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002506ParseResult MLFunctionParser::parseIfStmt() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002507 auto loc = getToken().getLoc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002508 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002509
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002510 IntegerSet *set = parseIntegerSetReference();
2511 if (!set)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002512 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002513
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002514 SmallVector<MLValue *, 4> operands;
2515 if (parseDimAndSymbolList(operands, set->getNumDims(), set->getNumOperands(),
2516 "integer set"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002517 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002518
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002519 IfStmt *ifStmt =
2520 builder.createIf(getEncodedSourceLocation(loc), operands, set);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002521
Chris Lattnere787b322018-08-08 11:14:57 -07002522 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002523
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002524 // When parsing of an if statement body fails, the IR contains
2525 // the if statement with the portion of the body that has been
2526 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002527 if (parseStmtBlock(thenClause))
2528 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002529
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002530 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002531 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002532 if (parseElseClause(elseClause))
2533 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002534 }
2535
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002536 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002537 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002538
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002539 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002540}
2541
2542ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2543 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002544 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002545 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002546 }
2547
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002548 return parseStmtBlock(elseClause);
2549}
2550
2551///
2552/// Parse a list of statements ending with `return` or `}`
2553///
2554ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002555 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2556 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002557 };
2558
Chris Lattnere787b322018-08-08 11:14:57 -07002559 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002560
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002561 // Parse statements till we see '}' or 'return'.
2562 // Return statement is parsed separately to emit a more intuitive error
2563 // when '}' is missing after the return statement.
2564 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002565 switch (getToken().getKind()) {
2566 default:
2567 if (parseOperation(createOpFunc))
2568 return ParseFailure;
2569 break;
2570 case Token::kw_for:
2571 if (parseForStmt())
2572 return ParseFailure;
2573 break;
2574 case Token::kw_if:
2575 if (parseIfStmt())
2576 return ParseFailure;
2577 break;
2578 } // end switch
2579 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002580
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002581 // Parse the return statement.
2582 if (getToken().is(Token::kw_return))
2583 if (parseOperation(createOpFunc))
2584 return ParseFailure;
2585
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002586 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002587}
2588
2589///
2590/// Parse `{` ml-stmt* `}`
2591///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002592ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002593 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2594 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002595 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002596 return ParseFailure;
2597
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002598 return ParseSuccess;
2599}
2600
Chris Lattner4c95a502018-06-23 16:03:42 -07002601//===----------------------------------------------------------------------===//
2602// Top-level entity parsing.
2603//===----------------------------------------------------------------------===//
2604
Chris Lattner2e595eb2018-07-10 10:08:27 -07002605namespace {
2606/// This parser handles entities that are only valid at the top level of the
2607/// file.
2608class ModuleParser : public Parser {
2609public:
2610 explicit ModuleParser(ParserState &state) : Parser(state) {}
2611
2612 ParseResult parseModule();
2613
2614private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002615 ParseResult finalizeModule();
2616
Chris Lattner2e595eb2018-07-10 10:08:27 -07002617 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002618 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002619
2620 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002621 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2622 SmallVectorImpl<StringRef> &argNames);
2623 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2624 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002625 ParseResult parseExtFunc();
2626 ParseResult parseCFGFunc();
2627 ParseResult parseMLFunc();
2628};
2629} // end anonymous namespace
2630
2631/// Affine map declaration.
2632///
2633/// affine-map-def ::= affine-map-id `=` affine-map-inline
2634///
2635ParseResult ModuleParser::parseAffineMapDef() {
2636 assert(getToken().is(Token::hash_identifier));
2637
2638 StringRef affineMapId = getTokenSpelling().drop_front();
2639
2640 // Check for redefinitions.
Nicolas Vasilache97298152018-08-27 10:10:42 -07002641 auto *&entry = getState().affineMapDefinitions[affineMapId];
2642 if (entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002643 return emitError("redefinition of affine map id '" + affineMapId + "'");
2644
2645 consumeToken(Token::hash_identifier);
2646
2647 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002648 if (parseToken(Token::equal,
2649 "expected '=' in affine map outlined definition"))
2650 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002651
Nicolas Vasilache97298152018-08-27 10:10:42 -07002652 entry = parseAffineMapInline();
2653 if (!entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002654 return ParseFailure;
2655
2656 return ParseSuccess;
2657}
2658
2659/// Integer set declaration.
2660///
2661/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2662///
2663ParseResult ModuleParser::parseIntegerSetDef() {
2664 assert(getToken().is(Token::double_at_identifier));
2665
2666 StringRef integerSetId = getTokenSpelling().drop_front(2);
2667
2668 // Check for redefinitions (a default entry is created if one doesn't exist)
Nicolas Vasilache97298152018-08-27 10:10:42 -07002669 auto *&entry = getState().integerSetDefinitions[integerSetId];
2670 if (entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002671 return emitError("redefinition of integer set id '" + integerSetId + "'");
2672
2673 consumeToken(Token::double_at_identifier);
2674
2675 // Parse the '='
2676 if (parseToken(Token::equal,
2677 "expected '=' in outlined integer set definition"))
2678 return ParseFailure;
2679
Nicolas Vasilache97298152018-08-27 10:10:42 -07002680 entry = parseIntegerSetInline();
2681 if (!entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002682 return ParseFailure;
2683
Chris Lattner2e595eb2018-07-10 10:08:27 -07002684 return ParseSuccess;
2685}
2686
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002687/// Parse a (possibly empty) list of MLFunction arguments with types.
2688///
2689/// ml-argument ::= ssa-id `:` type
2690/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2691///
2692ParseResult
2693ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2694 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002695 consumeToken(Token::l_paren);
2696
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002697 auto parseElt = [&]() -> ParseResult {
2698 // Parse argument name
2699 if (getToken().isNot(Token::percent_identifier))
2700 return emitError("expected SSA identifier");
2701
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002702 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002703 consumeToken(Token::percent_identifier);
2704 argNames.push_back(name);
2705
Chris Lattnerf7702a62018-07-23 17:30:01 -07002706 if (parseToken(Token::colon, "expected ':'"))
2707 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002708
2709 // Parse argument type
2710 auto elt = parseType();
2711 if (!elt)
2712 return ParseFailure;
2713 argTypes.push_back(elt);
2714
2715 return ParseSuccess;
2716 };
2717
Chris Lattner40746442018-07-21 14:32:09 -07002718 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002719}
2720
Chris Lattner2e595eb2018-07-10 10:08:27 -07002721/// Parse a function signature, starting with a name and including the parameter
2722/// list.
2723///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002724/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002725/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2726///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002727ParseResult
2728ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2729 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002730 if (getToken().isNot(Token::at_identifier))
2731 return emitError("expected a function identifier like '@foo'");
2732
2733 name = getTokenSpelling().drop_front();
2734 consumeToken(Token::at_identifier);
2735
2736 if (getToken().isNot(Token::l_paren))
2737 return emitError("expected '(' in function signature");
2738
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002739 SmallVector<Type *, 4> argTypes;
2740 ParseResult parseResult;
2741
2742 if (argNames)
2743 parseResult = parseMLArgumentList(argTypes, *argNames);
2744 else
2745 parseResult = parseTypeList(argTypes);
2746
2747 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002748 return ParseFailure;
2749
2750 // Parse the return type if present.
2751 SmallVector<Type *, 4> results;
2752 if (consumeIf(Token::arrow)) {
2753 if (parseTypeList(results))
2754 return ParseFailure;
2755 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002756 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002757 return ParseSuccess;
2758}
2759
2760/// External function declarations.
2761///
2762/// ext-func ::= `extfunc` function-signature
2763///
2764ParseResult ModuleParser::parseExtFunc() {
2765 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002766 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002767
2768 StringRef name;
2769 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002770 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002771 return ParseFailure;
2772
2773 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002774 auto *function = new ExtFunction(name, type);
2775 getModule()->getFunctions().push_back(function);
2776
2777 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002778 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002779 return emitError(loc,
2780 "redefinition of function named '" + name.str() + "'");
2781
Chris Lattner2e595eb2018-07-10 10:08:27 -07002782 return ParseSuccess;
2783}
2784
2785/// CFG function declarations.
2786///
2787/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2788///
2789ParseResult ModuleParser::parseCFGFunc() {
2790 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002791 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002792
2793 StringRef name;
2794 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002795 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002796 return ParseFailure;
2797
2798 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002799 auto *function = new CFGFunction(name, type);
2800 getModule()->getFunctions().push_back(function);
2801
2802 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002803 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002804 return emitError(loc,
2805 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002806
2807 return CFGFunctionParser(getState(), function).parseFunctionBody();
2808}
2809
2810/// ML function declarations.
2811///
2812/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2813///
2814ParseResult ModuleParser::parseMLFunc() {
2815 consumeToken(Token::kw_mlfunc);
2816
2817 StringRef name;
2818 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002819 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002820
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002821 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002822 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002823 return ParseFailure;
2824
2825 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002826 auto *function = MLFunction::create(name, type);
2827 getModule()->getFunctions().push_back(function);
2828
2829 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002830 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002831 return emitError(loc,
2832 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002833
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002834 // Create the parser.
2835 auto parser = MLFunctionParser(getState(), function);
2836
2837 // Add definitions of the function arguments.
2838 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2839 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2840 return ParseFailure;
2841 }
2842
2843 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002844}
2845
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002846/// Given an attribute that could refer to a function attribute in the remapping
2847/// table, walk it and rewrite it to use the mapped function. If it doesn't
2848/// refer to anything in the table, then it is returned unmodified.
2849static Attribute *
2850remapFunctionAttrs(Attribute *input,
2851 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2852 MLIRContext *context) {
2853 // Most attributes are trivially unrelated to function attributes, skip them
2854 // rapidly.
2855 if (!input->isOrContainsFunction())
2856 return input;
2857
2858 // If we have a function attribute, remap it.
2859 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2860 auto it = remappingTable.find(fnAttr);
2861 return it != remappingTable.end() ? it->second : input;
2862 }
2863
2864 // Otherwise, we must have an array attribute, remap the elements.
2865 auto *arrayAttr = cast<ArrayAttr>(input);
2866 SmallVector<Attribute *, 8> remappedElts;
2867 bool anyChange = false;
2868 for (auto *elt : arrayAttr->getValue()) {
2869 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2870 remappedElts.push_back(newElt);
2871 anyChange |= (elt != newElt);
2872 }
2873
2874 if (!anyChange)
2875 return input;
2876
2877 return ArrayAttr::get(remappedElts, context);
2878}
2879
2880/// Remap function attributes to resolve forward references to their actual
2881/// definition.
2882static void remapFunctionAttrsInOperation(
2883 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2884 for (auto attr : op->getAttrs()) {
2885 // Do the remapping, if we got the same thing back, then it must contain
2886 // functions that aren't getting remapped.
2887 auto *newVal =
2888 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2889 if (newVal == attr.second)
2890 continue;
2891
2892 // Otherwise, replace the existing attribute with the new one. It is safe
2893 // to mutate the attribute list while we walk it because underlying
2894 // attribute lists are uniqued and immortal.
2895 op->setAttr(attr.first, newVal);
2896 }
2897}
2898
Chris Lattner4613d9e2018-08-19 21:17:22 -07002899/// Finish the end of module parsing - when the result is valid, do final
2900/// checking.
2901ParseResult ModuleParser::finalizeModule() {
2902
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002903 // Resolve all forward references, building a remapping table of attributes.
2904 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002905 for (auto forwardRef : getState().functionForwardRefs) {
2906 auto name = forwardRef.first;
2907
2908 // Resolve the reference.
2909 auto *resolvedFunction = getModule()->getNamedFunction(name);
2910 if (!resolvedFunction)
2911 return emitError(forwardRef.second.second,
2912 "reference to undefined function '" + name.str() + "'");
2913
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002914 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2915 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002916 }
2917
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002918 // If there was nothing to remap, then we're done.
2919 if (remappingTable.empty())
2920 return ParseSuccess;
2921
2922 // Otherwise, walk the entire module replacing uses of one attribute set with
2923 // the correct ones.
2924 for (auto &fn : *getModule()) {
2925 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2926 for (auto &bb : *cfgFn) {
2927 for (auto &inst : bb) {
2928 remapFunctionAttrsInOperation(&inst, remappingTable);
2929 }
2930 }
2931 }
2932
2933 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2934 auto *mlFn = dyn_cast<MLFunction>(&fn);
2935 if (!mlFn)
2936 continue;
2937
2938 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2939 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2940 : remappingTable(remappingTable) {}
2941 void visitOperationStmt(OperationStmt *opStmt) {
2942 remapFunctionAttrsInOperation(opStmt, remappingTable);
2943 }
2944
2945 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2946 };
2947
2948 MLFnWalker(remappingTable).walk(mlFn);
2949 }
2950
2951 // Now that all references to the forward definition placeholders are
2952 // resolved, we can deallocate the placeholders.
2953 for (auto forwardRef : getState().functionForwardRefs)
2954 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002955 return ParseSuccess;
2956}
2957
Chris Lattnere79379a2018-06-22 10:39:19 -07002958/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002959ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002960 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002961 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002962 default:
2963 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002964 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002965
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002966 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002967 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002968 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002969
2970 // If we got an error token, then the lexer already emitted an error, just
2971 // stop. Someday we could introduce error recovery if there was demand for
2972 // it.
2973 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002974 return ParseFailure;
2975
2976 case Token::hash_identifier:
2977 if (parseAffineMapDef())
2978 return ParseFailure;
2979 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002980
Uday Bondhugulabc535622018-08-07 14:24:38 -07002981 case Token::double_at_identifier:
2982 if (parseIntegerSetDef())
2983 return ParseFailure;
2984 break;
2985
Chris Lattnere79379a2018-06-22 10:39:19 -07002986 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002987 if (parseExtFunc())
2988 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002989 break;
2990
Chris Lattner4c95a502018-06-23 16:03:42 -07002991 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002992 if (parseCFGFunc())
2993 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002994 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002995
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002996 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002997 if (parseMLFunc())
2998 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002999 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003000 }
3001 }
3002}
3003
3004//===----------------------------------------------------------------------===//
3005
3006/// This parses the file specified by the indicated SourceMgr and returns an
3007/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Chris Lattner7879f842018-09-02 22:01:45 -07003008Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr,
3009 MLIRContext *context) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003010
Chris Lattner2e595eb2018-07-10 10:08:27 -07003011 // This is the result module we are parsing into.
3012 std::unique_ptr<Module> module(new Module(context));
3013
Chris Lattner7879f842018-09-02 22:01:45 -07003014 ParserState state(sourceMgr, module.get());
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003015 if (ModuleParser(state).parseModule()) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07003016 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003017 }
Chris Lattner21e67f62018-07-06 10:46:19 -07003018
3019 // Make sure the parse module has no other structural problems detected by the
3020 // verifier.
Chris Lattner7879f842018-09-02 22:01:45 -07003021 //
3022 // TODO(clattner): The verifier should always emit diagnostics when we have
3023 // more location information available. We shouldn't need this hook.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003024 std::string errorResult;
3025 module->verify(&errorResult);
3026
3027 // We don't have location information for general verifier errors, so emit the
Chris Lattner7879f842018-09-02 22:01:45 -07003028 // error with an unknown location.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003029 if (!errorResult.empty()) {
Chris Lattner7879f842018-09-02 22:01:45 -07003030 context->emitDiagnostic(UnknownLoc::get(context), errorResult,
3031 MLIRContext::DiagnosticKind::Error);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003032 return nullptr;
3033 }
3034
Chris Lattner2e595eb2018-07-10 10:08:27 -07003035 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07003036}
Jacques Pienaarbd22d432018-09-03 07:38:31 -07003037
3038/// This parses the program string to a MLIR module if it was valid. If not, it
3039/// emits diagnostics and returns null.
3040Module *mlir::parseSourceString(StringRef moduleStr, MLIRContext *context) {
3041 auto memBuffer = MemoryBuffer::getMemBuffer(moduleStr);
3042 if (!memBuffer)
3043 return nullptr;
3044
3045 SourceMgr sourceMgr;
3046 sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
3047 return parseSourceFile(sourceMgr, context);
3048}