blob: b9b903cd2b5ef10671f329c37f4149cd61696bf3 [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:
Jacques Pienaardadee542018-09-08 18:37:27 -070060 ParserState(const llvm::SourceMgr &sourceMgr, Module *module)
Chris Lattner7879f842018-09-02 22:01:45 -070061 : 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
Chris Lattner791813d2018-09-07 09:08:13 -070071 // temporary function used to represent them.
72 llvm::DenseMap<Identifier, Function *> functionForwardRefs;
Chris Lattner4613d9e2018-08-19 21:17:22 -070073
Chris Lattnere79379a2018-06-22 10:39:19 -070074private:
Chris Lattner48af7d12018-07-09 19:05:38 -070075 ParserState(const ParserState &) = delete;
76 void operator=(const ParserState &) = delete;
77
78 friend class Parser;
79
80 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070081 MLIRContext *const context;
82
83 // This is the module we are parsing into.
84 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070085
86 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070087 Lexer lex;
88
89 // This is the next token that hasn't been consumed yet.
90 Token curToken;
91
Chris Lattner85ee1512018-07-25 11:15:20 -070092 // The active OperationSet we're parsing with.
93 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070094};
95} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070096
Chris Lattner48af7d12018-07-09 19:05:38 -070097namespace {
98
Chris Lattner992a1272018-08-07 12:02:37 -070099typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700100 CreateOperationFunction;
101
Chris Lattner48af7d12018-07-09 19:05:38 -0700102/// This class implement support for parsing global entities like types and
103/// shared entities like SSA names. It is intended to be subclassed by
104/// specialized subparsers that include state, e.g. when a local symbol table.
105class Parser {
106public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700107 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700108
Chris Lattner2e595eb2018-07-10 10:08:27 -0700109 Parser(ParserState &state) : builder(state.context), state(state) {}
110
111 // Helper methods to get stuff from the parser-global state.
112 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700113 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700114 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700115 OperationSet &getOperationSet() const { return state.operationSet; }
Jacques Pienaardadee542018-09-08 18:37:27 -0700116 const llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700117
118 /// Return the current token the parser is inspecting.
119 const Token &getToken() const { return state.curToken; }
120 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700121
Chris Lattner1628fa02018-08-23 14:32:25 -0700122 /// Encode the specified source location information into an attribute for
123 /// attachment to the IR.
Chris Lattner7879f842018-09-02 22:01:45 -0700124 Location *getEncodedSourceLocation(llvm::SMLoc loc) {
125 return state.lex.getEncodedSourceLocation(loc);
126 }
Chris Lattner1628fa02018-08-23 14:32:25 -0700127
Chris Lattnere79379a2018-06-22 10:39:19 -0700128 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700129 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700130 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700131 }
132 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700133
134 /// Advance the current lexer onto the next token.
135 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700136 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700137 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700138 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700139 }
140
141 /// Advance the current lexer onto the next token, asserting what the expected
142 /// current token is. This is preferred to the above method because it leads
143 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700144 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700145 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700146 consumeToken();
147 }
148
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700149 /// If the current token has the specified kind, consume it and return true.
150 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700151 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700152 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700153 return false;
154 consumeToken(kind);
155 return true;
156 }
157
Chris Lattnerf7702a62018-07-23 17:30:01 -0700158 /// Consume the specified token if present and return success. On failure,
159 /// output a diagnostic and return failure.
160 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
161
Chris Lattner40746442018-07-21 14:32:09 -0700162 /// Parse a comma-separated list of elements up until the specified end token.
163 ParseResult
164 parseCommaSeparatedListUntil(Token::Kind rightToken,
165 const std::function<ParseResult()> &parseElement,
166 bool allowEmptyList = true);
167
168 /// Parse a comma separated list of elements that must have at least one entry
169 /// in it.
170 ParseResult
171 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700172
Chris Lattnerf7e22732018-06-22 22:03:48 -0700173 // We have two forms of parsing methods - those that return a non-null
174 // pointer on success, and those that return a ParseResult to indicate whether
175 // they returned a failure. The second class fills in by-reference arguments
176 // as the results of their action.
177
Chris Lattnere79379a2018-06-22 10:39:19 -0700178 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700179 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700180 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700181 Type *parseTensorType();
182 Type *parseMemRefType();
183 Type *parseFunctionType();
184 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700185 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700186 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700187
Chris Lattner7121b802018-07-04 20:45:39 -0700188 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700189 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
190 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700191 Attribute *parseAttribute();
192 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
193
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700194 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700195 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700196 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700197 IntegerSet *parseIntegerSetInline();
198 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700199
Chris Lattner48af7d12018-07-09 19:05:38 -0700200private:
201 // The Parser is subclassed and reinstantiated. Do not add additional
202 // non-trivial state here, add it to the ParserState class.
203 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700204};
205} // end anonymous namespace
206
207//===----------------------------------------------------------------------===//
208// Helper methods.
209//===----------------------------------------------------------------------===//
210
Chris Lattner4c95a502018-06-23 16:03:42 -0700211ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700212 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700213 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700214 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700215 return ParseFailure;
216
Chris Lattner7879f842018-09-02 22:01:45 -0700217 getContext()->emitDiagnostic(getEncodedSourceLocation(loc), message,
218 MLIRContext::DiagnosticKind::Error);
Chris Lattnere79379a2018-06-22 10:39:19 -0700219 return ParseFailure;
220}
221
Chris Lattnerf7702a62018-07-23 17:30:01 -0700222/// Consume the specified token if present and return success. On failure,
223/// output a diagnostic and return failure.
224ParseResult Parser::parseToken(Token::Kind expectedToken,
225 const Twine &message) {
226 if (consumeIf(expectedToken))
227 return ParseSuccess;
228 return emitError(message);
229}
230
Chris Lattner40746442018-07-21 14:32:09 -0700231/// Parse a comma separated list of elements that must have at least one entry
232/// in it.
233ParseResult Parser::parseCommaSeparatedList(
234 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700235 // Non-empty case starts with an element.
236 if (parseElement())
237 return ParseFailure;
238
239 // Otherwise we have a list of comma separated elements.
240 while (consumeIf(Token::comma)) {
241 if (parseElement())
242 return ParseFailure;
243 }
Chris Lattner40746442018-07-21 14:32:09 -0700244 return ParseSuccess;
245}
246
247/// Parse a comma-separated list of elements, terminated with an arbitrary
248/// token. This allows empty lists if allowEmptyList is true.
249///
250/// abstract-list ::= rightToken // if allowEmptyList == true
251/// abstract-list ::= element (',' element)* rightToken
252///
253ParseResult Parser::parseCommaSeparatedListUntil(
254 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
255 bool allowEmptyList) {
256 // Handle the empty case.
257 if (getToken().is(rightToken)) {
258 if (!allowEmptyList)
259 return emitError("expected list element");
260 consumeToken(rightToken);
261 return ParseSuccess;
262 }
263
Chris Lattnerf7702a62018-07-23 17:30:01 -0700264 if (parseCommaSeparatedList(parseElement) ||
265 parseToken(rightToken, "expected ',' or '" +
266 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700267 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700268
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269 return ParseSuccess;
270}
Chris Lattnere79379a2018-06-22 10:39:19 -0700271
272//===----------------------------------------------------------------------===//
273// Type Parsing
274//===----------------------------------------------------------------------===//
275
Chris Lattnerc3251192018-07-27 13:09:58 -0700276/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700277///
Chris Lattnerc3251192018-07-27 13:09:58 -0700278/// type ::= integer-type
279/// | float-type
280/// | other-type
281/// | vector-type
282/// | tensor-type
283/// | memref-type
284/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700285///
Chris Lattnerc3251192018-07-27 13:09:58 -0700286/// float-type ::= `f16` | `bf16` | `f32` | `f64`
287/// other-type ::= `affineint` | `tf_control`
288///
289Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700290 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700291 default:
292 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700293 case Token::kw_memref:
294 return parseMemRefType();
295 case Token::kw_tensor:
296 return parseTensorType();
297 case Token::kw_vector:
298 return parseVectorType();
299 case Token::l_paren:
300 return parseFunctionType();
301 // integer-type
302 case Token::inttype: {
303 auto width = getToken().getIntTypeBitwidth();
304 if (!width.hasValue())
305 return (emitError("invalid integer width"), nullptr);
Nicolas Vasilache1b8c0842018-08-27 10:26:15 -0700306 if (width > IntegerType::kMaxWidth)
307 return (emitError("integer bitwidth is limited to " +
308 Twine(IntegerType::kMaxWidth) + " bits"),
309 nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700310 consumeToken(Token::inttype);
311 return builder.getIntegerType(width.getValue());
312 }
313
314 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700315 case Token::kw_bf16:
316 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700317 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700318 case Token::kw_f16:
319 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700320 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321 case Token::kw_f32:
322 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700323 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324 case Token::kw_f64:
325 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700326 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700327
328 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700329 case Token::kw_affineint:
330 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700331 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700332 case Token::kw_tf_control:
333 consumeToken(Token::kw_tf_control);
334 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700335 case Token::kw_tf_string:
336 consumeToken(Token::kw_tf_string);
337 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700338 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700339}
340
341/// Parse a vector type.
342///
343/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
344/// const-dimension-list ::= (integer-literal `x`)+
345///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700346VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347 consumeToken(Token::kw_vector);
348
Chris Lattnerf7702a62018-07-23 17:30:01 -0700349 if (parseToken(Token::less, "expected '<' in vector type"))
350 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351
Chris Lattner48af7d12018-07-09 19:05:38 -0700352 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700353 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700354
355 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700356 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700357 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700358 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700359 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700360 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700361 dimensions.push_back(dimension.getValue());
362
363 consumeToken(Token::integer);
364
365 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700366 if (getToken().isNot(Token::bare_identifier) ||
367 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700368 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700369
370 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700371 if (getTokenSpelling().size() != 1)
372 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700373
374 // Consume the 'x'.
375 consumeToken(Token::bare_identifier);
376 }
377
378 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700379 auto typeLoc = getToken().getLoc();
380 auto *elementType = parseType();
381 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700382 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700383
Chris Lattnerc3251192018-07-27 13:09:58 -0700384 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
385 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700386
Chris Lattnerf7e22732018-06-22 22:03:48 -0700387 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700388}
389
390/// Parse a dimension list of a tensor or memref type. This populates the
391/// dimension list, returning -1 for the '?' dimensions.
392///
393/// dimension-list-ranked ::= (dimension `x`)*
394/// dimension ::= `?` | integer-literal
395///
396ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700397 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700398 if (consumeIf(Token::question)) {
399 dimensions.push_back(-1);
400 } else {
401 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700402 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700403 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
404 return emitError("invalid dimension");
405 dimensions.push_back((int)dimension.getValue());
406 consumeToken(Token::integer);
407 }
408
409 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700410 if (getToken().isNot(Token::bare_identifier) ||
411 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412 return emitError("expected 'x' in dimension list");
413
414 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700415 if (getTokenSpelling().size() != 1)
416 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700417
418 // Consume the 'x'.
419 consumeToken(Token::bare_identifier);
420 }
421
422 return ParseSuccess;
423}
424
425/// Parse a tensor type.
426///
427/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
428/// dimension-list ::= dimension-list-ranked | `??`
429///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700430Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700431 consumeToken(Token::kw_tensor);
432
Chris Lattnerf7702a62018-07-23 17:30:01 -0700433 if (parseToken(Token::less, "expected '<' in tensor type"))
434 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700435
436 bool isUnranked;
437 SmallVector<int, 4> dimensions;
438
439 if (consumeIf(Token::questionquestion)) {
440 isUnranked = true;
441 } else {
442 isUnranked = false;
443 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700444 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700445 }
446
447 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700448 auto typeLoc = getToken().getLoc();
449 auto *elementType = parseType();
450 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700451 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700452
Chris Lattnerc3251192018-07-27 13:09:58 -0700453 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
454 !isa<VectorType>(elementType))
455 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700456
MLIR Team355ec862018-06-23 18:09:09 -0700457 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700458 return builder.getTensorType(elementType);
459 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700460}
461
462/// Parse a memref type.
463///
464/// memref-type ::= `memref` `<` dimension-list-ranked element-type
465/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
466///
467/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
468/// memory-space ::= integer-literal /* | TODO: address-space-id */
469///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700470Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700471 consumeToken(Token::kw_memref);
472
Chris Lattnerf7702a62018-07-23 17:30:01 -0700473 if (parseToken(Token::less, "expected '<' in memref type"))
474 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700475
476 SmallVector<int, 4> dimensions;
477 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700478 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700479
480 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700481 auto typeLoc = getToken().getLoc();
482 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700483 if (!elementType)
484 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700485
Chris Lattnerc3251192018-07-27 13:09:58 -0700486 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
487 !isa<VectorType>(elementType))
488 return (emitError(typeLoc, "invalid memref element type"), nullptr);
489
MLIR Team718c82f2018-07-16 09:45:22 -0700490 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700491 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700492 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700493 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700494
MLIR Team718c82f2018-07-16 09:45:22 -0700495 auto parseElt = [&]() -> ParseResult {
496 if (getToken().is(Token::integer)) {
497 // Parse memory space.
498 if (parsedMemorySpace)
499 return emitError("multiple memory spaces specified in memref type");
500 auto v = getToken().getUnsignedIntegerValue();
501 if (!v.hasValue())
502 return emitError("invalid memory space in memref type");
503 memorySpace = v.getValue();
504 consumeToken(Token::integer);
505 parsedMemorySpace = true;
506 } else {
507 // Parse affine map.
508 if (parsedMemorySpace)
509 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700510 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700511 if (affineMap == nullptr)
512 return ParseFailure;
513 affineMapComposition.push_back(affineMap);
514 }
515 return ParseSuccess;
516 };
517
Chris Lattner413db6a2018-07-25 12:55:50 -0700518 // Parse a list of mappings and address space if present.
519 if (consumeIf(Token::comma)) {
520 // Parse comma separated list of affine maps, followed by memory space.
521 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
522 /*allowEmptyList=*/false)) {
523 return nullptr;
524 }
525 } else {
526 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
527 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700528 }
MLIR Team718c82f2018-07-16 09:45:22 -0700529
530 return MemRefType::get(dimensions, elementType, affineMapComposition,
531 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700532}
533
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700534/// Parse a function type.
535///
536/// function-type ::= type-list-parens `->` type-list
537///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700538Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700539 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700540
Chris Lattnerf7702a62018-07-23 17:30:01 -0700541 SmallVector<Type *, 4> arguments, results;
542 if (parseTypeList(arguments) ||
543 parseToken(Token::arrow, "expected '->' in function type") ||
544 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700545 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700546
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700547 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700548}
549
Chris Lattner1604e472018-07-23 08:42:19 -0700550/// Parse a list of types without an enclosing parenthesis. The list must have
551/// at least one member.
552///
553/// type-list-no-parens ::= type (`,` type)*
554///
555ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
556 auto parseElt = [&]() -> ParseResult {
557 auto elt = parseType();
558 elements.push_back(elt);
559 return elt ? ParseSuccess : ParseFailure;
560 };
561
562 return parseCommaSeparatedList(parseElt);
563}
564
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700565/// Parse a "type list", which is a singular type, or a parenthesized list of
566/// types.
567///
568/// type-list ::= type-list-parens | type
569/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700570/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700571///
James Molloy0ff71542018-07-23 16:56:32 -0700572ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700573 auto parseElt = [&]() -> ParseResult {
574 auto elt = parseType();
575 elements.push_back(elt);
576 return elt ? ParseSuccess : ParseFailure;
577 };
578
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700579 // If there is no parens, then it must be a singular type.
580 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700581 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700582
Chris Lattner40746442018-07-21 14:32:09 -0700583 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700584 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700585
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700586 return ParseSuccess;
587}
588
Chris Lattner4c95a502018-06-23 16:03:42 -0700589//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700590// Attribute parsing.
591//===----------------------------------------------------------------------===//
592
Chris Lattner1aa46322018-08-21 17:55:22 -0700593/// Given a parsed reference to a function name like @foo and a type that it
594/// corresponds to, resolve it to a concrete function object (possibly
595/// synthesizing a forward reference) or emit an error and return null on
596/// failure.
597Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
598 FunctionType *type) {
599 Identifier name = builder.getIdentifier(nameStr.drop_front());
600
601 // See if the function has already been defined in the module.
602 Function *function = getModule()->getNamedFunction(name);
603
604 // If not, get or create a forward reference to one.
605 if (!function) {
606 auto &entry = state.functionForwardRefs[name];
Chris Lattner791813d2018-09-07 09:08:13 -0700607 if (!entry)
608 entry = new ExtFunction(getEncodedSourceLocation(nameLoc), name, type);
609 function = entry;
Chris Lattner1aa46322018-08-21 17:55:22 -0700610 }
611
612 if (function->getType() != type)
613 return (emitError(nameLoc, "reference to function with mismatched type"),
614 nullptr);
615 return function;
616}
617
Chris Lattner7121b802018-07-04 20:45:39 -0700618/// Attribute parsing.
619///
620/// attribute-value ::= bool-literal
621/// | integer-literal
622/// | float-literal
623/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700624/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700625/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700626/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700627///
628Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700629 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700630 case Token::kw_true:
631 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700632 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700633 case Token::kw_false:
634 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700635 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700636
Jacques Pienaar84491092018-07-31 17:15:15 -0700637 case Token::floatliteral: {
638 auto val = getToken().getFloatingPointValue();
639 if (!val.hasValue())
640 return (emitError("floating point value too large for attribute"),
641 nullptr);
642 consumeToken(Token::floatliteral);
643 return builder.getFloatAttr(val.getValue());
644 }
Chris Lattner7121b802018-07-04 20:45:39 -0700645 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700646 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700647 if (!val.hasValue() || (int64_t)val.getValue() < 0)
648 return (emitError("integer too large for attribute"), nullptr);
649 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700650 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700651 }
652
653 case Token::minus: {
654 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700655 if (getToken().is(Token::integer)) {
656 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700657 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
658 return (emitError("integer too large for attribute"), nullptr);
659 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700660 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700661 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700662 if (getToken().is(Token::floatliteral)) {
663 auto val = getToken().getFloatingPointValue();
664 if (!val.hasValue())
665 return (emitError("floating point value too large for attribute"),
666 nullptr);
667 consumeToken(Token::floatliteral);
668 return builder.getFloatAttr(-val.getValue());
669 }
Chris Lattner7121b802018-07-04 20:45:39 -0700670
671 return (emitError("expected constant integer or floating point value"),
672 nullptr);
673 }
674
675 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700676 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700677 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700678 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700679 }
680
Chris Lattner85ee1512018-07-25 11:15:20 -0700681 case Token::l_square: {
682 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700683 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700684
685 auto parseElt = [&]() -> ParseResult {
686 elements.push_back(parseAttribute());
687 return elements.back() ? ParseSuccess : ParseFailure;
688 };
689
Chris Lattner85ee1512018-07-25 11:15:20 -0700690 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700691 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700692 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700693 }
James Molloyf0d2f442018-08-03 01:54:46 -0700694 case Token::hash_identifier:
695 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700696 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700697 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700698 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700699 return (emitError("expected constant attribute value"), nullptr);
700 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700701
702 case Token::at_identifier: {
703 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700704 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700705 consumeToken(Token::at_identifier);
706
707 if (parseToken(Token::colon, "expected ':' and function type"))
708 return nullptr;
709 auto typeLoc = getToken().getLoc();
710 Type *type = parseType();
711 if (!type)
712 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700713 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700714 if (!fnType)
715 return (emitError(typeLoc, "expected function type"), nullptr);
716
Chris Lattner1aa46322018-08-21 17:55:22 -0700717 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
718 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700719 }
720
James Molloyf0d2f442018-08-03 01:54:46 -0700721 default: {
722 if (Type *type = parseType())
723 return builder.getTypeAttr(type);
724 return nullptr;
725 }
726 }
Chris Lattner7121b802018-07-04 20:45:39 -0700727}
728
Chris Lattner7121b802018-07-04 20:45:39 -0700729/// Attribute dictionary.
730///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700731/// attribute-dict ::= `{` `}`
732/// | `{` attribute-entry (`,` attribute-entry)* `}`
733/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700734///
James Molloy0ff71542018-07-23 16:56:32 -0700735ParseResult
736Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700737 consumeToken(Token::l_brace);
738
739 auto parseElt = [&]() -> ParseResult {
740 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700741 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
742 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700743 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700744 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700745 consumeToken();
746
Chris Lattnerf7702a62018-07-23 17:30:01 -0700747 if (parseToken(Token::colon, "expected ':' in attribute list"))
748 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700749
750 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700751 if (!attr)
752 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700753
754 attributes.push_back({nameId, attr});
755 return ParseSuccess;
756 };
757
Chris Lattner40746442018-07-21 14:32:09 -0700758 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700759 return ParseFailure;
760
761 return ParseSuccess;
762}
763
764//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700765// Polyhedral structures.
766//===----------------------------------------------------------------------===//
767
Chris Lattner2e595eb2018-07-10 10:08:27 -0700768/// Lower precedence ops (all at the same precedence level). LNoOp is false in
769/// the boolean sense.
770enum AffineLowPrecOp {
771 /// Null value.
772 LNoOp,
773 Add,
774 Sub
775};
MLIR Teamf85a6262018-06-27 11:03:08 -0700776
Chris Lattner2e595eb2018-07-10 10:08:27 -0700777/// Higher precedence ops - all at the same precedence level. HNoOp is false in
778/// the boolean sense.
779enum AffineHighPrecOp {
780 /// Null value.
781 HNoOp,
782 Mul,
783 FloorDiv,
784 CeilDiv,
785 Mod
786};
Chris Lattner7121b802018-07-04 20:45:39 -0700787
Chris Lattner2e595eb2018-07-10 10:08:27 -0700788namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700789/// This is a specialized parser for affine structures (affine maps, affine
790/// expressions, and integer sets), maintaining the state transient to their
791/// bodies.
792class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700793public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700794 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700795
Chris Lattner2e595eb2018-07-10 10:08:27 -0700796 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700797 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700798
Chris Lattner2e595eb2018-07-10 10:08:27 -0700799private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700800 // Binary affine op parsing.
801 AffineLowPrecOp consumeIfLowPrecOp();
802 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700803
Chris Lattner2e595eb2018-07-10 10:08:27 -0700804 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700805 ParseResult parseDimIdList(unsigned &numDims);
806 ParseResult parseSymbolIdList(unsigned &numSymbols);
807 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700808
809 AffineExpr *parseAffineExpr();
810 AffineExpr *parseParentheticalExpr();
811 AffineExpr *parseNegateExpression(AffineExpr *lhs);
812 AffineExpr *parseIntegerExpr();
813 AffineExpr *parseBareIdExpr();
814
815 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700816 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700817 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
818 AffineExpr *rhs);
819 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
820 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
821 AffineLowPrecOp llhsOp);
822 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700823 AffineHighPrecOp llhsOp,
824 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700825 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700826
827private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700828 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700829};
830} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700831
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700832/// Create an affine binary high precedence op expression (mul's, div's, mod).
833/// opLoc is the location of the op token to be used to report errors
834/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700835AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
836 AffineExpr *lhs,
837 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700838 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700839 switch (op) {
840 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700841 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700842 emitError(opLoc, "non-affine expression: at least one of the multiply "
843 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700844 return nullptr;
845 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700846 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700847 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700848 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700849 emitError(opLoc, "non-affine expression: right operand of floordiv "
850 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700851 return nullptr;
852 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700853 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700854 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700855 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700856 emitError(opLoc, "non-affine expression: right operand of ceildiv "
857 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700858 return nullptr;
859 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700860 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700861 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700862 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863 emitError(opLoc, "non-affine expression: right operand of mod "
864 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700865 return nullptr;
866 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700867 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700868 case HNoOp:
869 llvm_unreachable("can't create affine expression for null high prec op");
870 return nullptr;
871 }
872}
873
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700874/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700875AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
876 AffineExpr *lhs,
877 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700878 switch (op) {
879 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700880 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700881 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700882 return builder.getAddExpr(
883 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700884 case AffineLowPrecOp::LNoOp:
885 llvm_unreachable("can't create affine expression for null low prec op");
886 return nullptr;
887 }
888}
889
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700890/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700891/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700892AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700893 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700894 case Token::plus:
895 consumeToken(Token::plus);
896 return AffineLowPrecOp::Add;
897 case Token::minus:
898 consumeToken(Token::minus);
899 return AffineLowPrecOp::Sub;
900 default:
901 return AffineLowPrecOp::LNoOp;
902 }
903}
904
905/// Consume this token if it is a higher precedence affine op (there are only
906/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700907AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700908 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700909 case Token::star:
910 consumeToken(Token::star);
911 return Mul;
912 case Token::kw_floordiv:
913 consumeToken(Token::kw_floordiv);
914 return FloorDiv;
915 case Token::kw_ceildiv:
916 consumeToken(Token::kw_ceildiv);
917 return CeilDiv;
918 case Token::kw_mod:
919 consumeToken(Token::kw_mod);
920 return Mod;
921 default:
922 return HNoOp;
923 }
924}
925
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700926/// Parse a high precedence op expression list: mul, div, and mod are high
927/// precedence binary ops, i.e., parse a
928/// expr_1 op_1 expr_2 op_2 ... expr_n
929/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
930/// All affine binary ops are left associative.
931/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
932/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700933/// null. llhsOpLoc is the location of the llhsOp token that will be used to
934/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700935AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
936 AffineHighPrecOp llhsOp,
937 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700938 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700939 if (!lhs)
940 return nullptr;
941
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700942 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700943 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700944 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700945 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700946 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700947 if (!expr)
948 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700949 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700950 }
951 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700952 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 }
954
955 // This is the last operand in this expression.
956 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700957 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958
959 // No llhs, 'lhs' itself is the expression.
960 return lhs;
961}
962
963/// Parse an affine expression inside parentheses.
964///
965/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700966AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700967 if (parseToken(Token::l_paren, "expected '('"))
968 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700969 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700970 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700971
Chris Lattner2e595eb2018-07-10 10:08:27 -0700972 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700973 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700974 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700975 if (parseToken(Token::r_paren, "expected ')'"))
976 return nullptr;
977
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700978 return expr;
979}
980
981/// Parse the negation expression.
982///
983/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700984AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700985 if (parseToken(Token::minus, "expected '-'"))
986 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700987
Chris Lattner2e595eb2018-07-10 10:08:27 -0700988 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700989 // Since negation has the highest precedence of all ops (including high
990 // precedence ops) but lower than parentheses, we are only going to use
991 // parseAffineOperandExpr instead of parseAffineExpr here.
992 if (!operand)
993 // Extra error message although parseAffineOperandExpr would have
994 // complained. Leads to a better diagnostic.
995 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700996 auto *minusOne = builder.getConstantExpr(-1);
997 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700998}
999
1000/// Parse a bare id that may appear in an affine expression.
1001///
1002/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -07001003AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001004 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001005 return (emitError("expected bare identifier"), nullptr);
1006
Chris Lattner48af7d12018-07-09 19:05:38 -07001007 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001008 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001009 if (entry.first == sRef) {
1010 consumeToken(Token::bare_identifier);
1011 return entry.second;
1012 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001013 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001014
1015 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001016}
1017
1018/// Parse a positive integral constant appearing in an affine expression.
1019///
1020/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001021AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001022 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001023 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001024 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001025
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001026 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001027 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001028}
1029
1030/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001031/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1032/// operator, the rhs of which is being parsed. This is used to determine
1033/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001034// Eg: for an expression without parentheses (like i + j + k + l), each
1035// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1036// operand expression, it's an op expression and will be parsed via
1037// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1038// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001039AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001040 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001041 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001042 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001043 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001044 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001045 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001047 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001048 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001049 case Token::kw_ceildiv:
1050 case Token::kw_floordiv:
1051 case Token::kw_mod:
1052 case Token::plus:
1053 case Token::star:
1054 if (lhs)
1055 emitError("missing right operand of binary operator");
1056 else
1057 emitError("missing left operand of binary operator");
1058 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001059 default:
1060 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001061 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001062 else
1063 emitError("expected affine expression");
1064 return nullptr;
1065 }
1066}
1067
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001068/// Parse affine expressions that are bare-id's, integer constants,
1069/// parenthetical affine expressions, and affine op expressions that are a
1070/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001071///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001072/// All binary op's associate from left to right.
1073///
1074/// {add, sub} have lower precedence than {mul, div, and mod}.
1075///
Uday Bondhugula76345202018-07-09 13:47:52 -07001076/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1077/// ceildiv, and mod are at the same higher precedence level. Negation has
1078/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001079///
1080/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001081/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1082/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1083/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084/// associativity.
1085///
1086/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001087/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1088/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001089AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1090 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001091 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001092 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001093 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001094
1095 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001096 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001097 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001098 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001099 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001100 }
1101 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001102 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001103 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001104 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001105 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001106 // We have a higher precedence op here. Get the rhs operand for the llhs
1107 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001108 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001109 if (!highRes)
1110 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001111
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001112 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001113 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001114 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001115 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001116
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001117 // Recurse for subsequent low prec op's after the affine high prec op
1118 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001119 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1120 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001121 return expr;
1122 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001123 // Last operand in the expression list.
1124 if (llhs)
1125 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1126 // No llhs, 'lhs' itself is the expression.
1127 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001128}
1129
1130/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001131/// affine-expr ::= `(` affine-expr `)`
1132/// | `-` affine-expr
1133/// | affine-expr `+` affine-expr
1134/// | affine-expr `-` affine-expr
1135/// | affine-expr `*` affine-expr
1136/// | affine-expr `floordiv` affine-expr
1137/// | affine-expr `ceildiv` affine-expr
1138/// | affine-expr `mod` affine-expr
1139/// | bare-id
1140/// | integer-literal
1141///
1142/// Additional conditions are checked depending on the production. For eg., one
1143/// of the operands for `*` has to be either constant/symbolic; the second
1144/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001145AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001146 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001147}
1148
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001149/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001150/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001151/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001152ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001153 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001154 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001155
1156 auto name = getTokenSpelling();
1157 for (auto entry : dimsAndSymbols) {
1158 if (entry.first == name)
1159 return emitError("redefinition of identifier '" + Twine(name) + "'");
1160 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001161 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001162
1163 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001164 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001165}
1166
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001167/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001168ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001169 consumeToken(Token::l_square);
1170 auto parseElt = [&]() -> ParseResult {
1171 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1172 return parseIdentifierDefinition(symbol);
1173 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001174 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001175}
1176
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001177/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001178ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001179 if (parseToken(Token::l_paren,
1180 "expected '(' at start of dimensional identifiers list"))
1181 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001182
Chris Lattner413db6a2018-07-25 12:55:50 -07001183 auto parseElt = [&]() -> ParseResult {
1184 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1185 return parseIdentifierDefinition(dimension);
1186 };
Chris Lattner40746442018-07-21 14:32:09 -07001187 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001188}
1189
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001190/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001191///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001192/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1193/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1194/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001195///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001196/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001197AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001198 unsigned numDims = 0, numSymbols = 0;
1199
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001200 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001201 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001202 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001203
1204 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001205 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001206 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001207 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001208 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001209
1210 if (parseToken(Token::arrow, "expected '->' or '['") ||
1211 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001212 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001213
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001214 SmallVector<AffineExpr *, 4> exprs;
1215 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001216 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001217 ParseResult res = elt ? ParseSuccess : ParseFailure;
1218 exprs.push_back(elt);
1219 return res;
1220 };
1221
1222 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001223 // affine expressions); the list cannot be empty.
1224 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001225 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001226 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001227
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001228 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001229 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1230 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1231 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001232 // TODO: check if sizes are non-negative whenever they are constant.
1233 SmallVector<AffineExpr *, 4> rangeSizes;
1234 if (consumeIf(Token::kw_size)) {
1235 // Location of the l_paren token (if it exists) for error reporting later.
1236 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001237 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1238 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001239
1240 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001241 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001242 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001243 if (!elt)
1244 return ParseFailure;
1245
1246 if (!elt->isSymbolicOrConstant())
1247 return emitError(loc,
1248 "size expressions cannot refer to dimension values");
1249
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001250 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001251 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001252 };
1253
Chris Lattner40746442018-07-21 14:32:09 -07001254 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001255 return nullptr;
1256 if (exprs.size() > rangeSizes.size())
1257 return (emitError(loc, "fewer range sizes than range expressions"),
1258 nullptr);
1259 if (exprs.size() < rangeSizes.size())
1260 return (emitError(loc, "more range sizes than range expressions"),
1261 nullptr);
1262 }
1263
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001264 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001265 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001266}
1267
Chris Lattner2e595eb2018-07-10 10:08:27 -07001268AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001269 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001270}
1271
MLIR Team718c82f2018-07-16 09:45:22 -07001272AffineMap *Parser::parseAffineMapReference() {
1273 if (getToken().is(Token::hash_identifier)) {
1274 // Parse affine map identifier and verify that it exists.
1275 StringRef affineMapId = getTokenSpelling().drop_front();
1276 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1277 return (emitError("undefined affine map id '" + affineMapId + "'"),
1278 nullptr);
1279 consumeToken(Token::hash_identifier);
1280 return getState().affineMapDefinitions[affineMapId];
1281 }
1282 // Try to parse inline affine map.
1283 return parseAffineMapInline();
1284}
1285
MLIR Teamf85a6262018-06-27 11:03:08 -07001286//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001287// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001288//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001289
Chris Lattner7f9cc272018-07-19 08:35:28 -07001290namespace {
1291/// This class contains parser state that is common across CFG and ML functions,
1292/// notably for dealing with operations and SSA values.
1293class FunctionParser : public Parser {
1294public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001295 enum class Kind { CFGFunc, MLFunc };
1296
1297 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001298
Chris Lattner6119d382018-07-20 18:41:34 -07001299 /// After the function is finished parsing, this function checks to see if
1300 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001301 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001302
1303 /// This represents a use of an SSA value in the program. The first two
1304 /// entries in the tuple are the name and result number of a reference. The
1305 /// third is the location of the reference, which is used in case this ends up
1306 /// being a use of an undefined value.
1307 struct SSAUseInfo {
1308 StringRef name; // Value name, e.g. %42 or %abc
1309 unsigned number; // Number, specified with #12
1310 SMLoc loc; // Location of first definition or use.
1311 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001312
1313 /// Given a reference to an SSA value and its type, return a reference. This
1314 /// returns null on failure.
1315 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1316
1317 /// Register a definition of a value with the symbol table.
1318 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1319
1320 // SSA parsing productions.
1321 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001322 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001323
1324 template <typename ResultType>
1325 ResultType parseSSADefOrUseAndType(
1326 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1327
1328 SSAValue *parseSSAUseAndType() {
1329 return parseSSADefOrUseAndType<SSAValue *>(
1330 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1331 return resolveSSAUse(useInfo, type);
1332 });
1333 }
Chris Lattner40746442018-07-21 14:32:09 -07001334
1335 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001336 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001337 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1338 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001339
1340 // Operations
1341 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001342 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1343 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001344
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001345protected:
1346 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1347
Chris Lattner7f9cc272018-07-19 08:35:28 -07001348private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001349 /// Kind indicates if this is CFG or ML function parser.
1350 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001351 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001352 /// their name. This has one entry per result number.
1353 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1354
1355 /// These are all of the placeholders we've made along with the location of
1356 /// their first reference, to allow checking for use of undefined values.
1357 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1358
1359 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1360
1361 /// Return true if this is a forward reference.
1362 bool isForwardReferencePlaceholder(SSAValue *value) {
1363 return forwardReferencePlaceholders.count(value);
1364 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001365};
1366} // end anonymous namespace
1367
Chris Lattner6119d382018-07-20 18:41:34 -07001368/// Create and remember a new placeholder for a forward reference.
1369SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1370 Type *type) {
1371 // Forward references are always created as instructions, even in ML
1372 // functions, because we just need something with a def/use chain.
1373 //
1374 // We create these placeholders as having an empty name, which we know cannot
1375 // be created through normal user input, allowing us to distinguish them.
1376 auto name = Identifier::get("placeholder", getContext());
Chris Lattnerfc647d52018-08-27 21:05:16 -07001377 auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
1378 /*operands=*/{}, type,
1379 /*attributes=*/{}, getContext());
Chris Lattner6119d382018-07-20 18:41:34 -07001380 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1381 return inst->getResult(0);
1382}
1383
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001384/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001385/// it specifies. This returns null on failure.
1386SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001387 auto &entries = values[useInfo.name];
1388
Chris Lattner7f9cc272018-07-19 08:35:28 -07001389 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001390 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1391 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001392 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001393 if (result->getType() == type)
1394 return result;
1395
Chris Lattner6119d382018-07-20 18:41:34 -07001396 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1397 "' expects different type than prior uses");
1398 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001399 return nullptr;
1400 }
1401
Chris Lattner6119d382018-07-20 18:41:34 -07001402 // Make sure we have enough slots for this.
1403 if (entries.size() <= useInfo.number)
1404 entries.resize(useInfo.number + 1);
1405
1406 // If the value has already been defined and this is an overly large result
1407 // number, diagnose that.
1408 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1409 return (emitError(useInfo.loc, "reference to invalid result number"),
1410 nullptr);
1411
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001412 // Otherwise, this is a forward reference. If we are in ML function return
1413 // an error. In CFG function, create a placeholder and remember
1414 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001415 if (getKind() == Kind::MLFunc)
1416 return (
1417 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1418 nullptr);
1419
Chris Lattner6119d382018-07-20 18:41:34 -07001420 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1421 entries[useInfo.number].first = result;
1422 entries[useInfo.number].second = useInfo.loc;
1423 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001424}
1425
1426/// Register a definition of a value with the symbol table.
1427ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001428 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001429
Chris Lattner6119d382018-07-20 18:41:34 -07001430 // Make sure there is a slot for this value.
1431 if (entries.size() <= useInfo.number)
1432 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001433
Chris Lattner6119d382018-07-20 18:41:34 -07001434 // If we already have an entry for this, check to see if it was a definition
1435 // or a forward reference.
1436 if (auto *existing = entries[useInfo.number].first) {
1437 if (!isForwardReferencePlaceholder(existing)) {
1438 emitError(useInfo.loc,
1439 "redefinition of SSA value '" + useInfo.name + "'");
1440 return emitError(entries[useInfo.number].second,
1441 "previously defined here");
1442 }
1443
1444 // If it was a forward reference, update everything that used it to use the
1445 // actual definition instead, delete the forward ref, and remove it from our
1446 // set of forward references we track.
1447 existing->replaceAllUsesWith(value);
1448 existing->getDefiningInst()->destroy();
1449 forwardReferencePlaceholders.erase(existing);
1450 }
1451
1452 entries[useInfo.number].first = value;
1453 entries[useInfo.number].second = useInfo.loc;
1454 return ParseSuccess;
1455}
1456
1457/// After the function is finished parsing, this function checks to see if
1458/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001459ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001460 // Check for any forward references that are left. If we find any, error out.
1461 if (!forwardReferencePlaceholders.empty()) {
1462 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1463 // Iteration over the map isn't determinstic, so sort by source location.
1464 for (auto entry : forwardReferencePlaceholders)
1465 errors.push_back({entry.second.getPointer(), entry.first});
1466 llvm::array_pod_sort(errors.begin(), errors.end());
1467
1468 for (auto entry : errors)
1469 emitError(SMLoc::getFromPointer(entry.first),
1470 "use of undeclared SSA value name");
1471 return ParseFailure;
1472 }
1473
1474 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001475}
1476
Chris Lattner78276e32018-07-07 15:48:26 -07001477/// Parse a SSA operand for an instruction or statement.
1478///
James Molloy61a656c2018-07-22 15:45:24 -07001479/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001480///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001481ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001482 result.name = getTokenSpelling();
1483 result.number = 0;
1484 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001485 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1486 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001487
1488 // If we have an affine map ID, it is a result number.
1489 if (getToken().is(Token::hash_identifier)) {
1490 if (auto value = getToken().getHashIdentifierNumber())
1491 result.number = value.getValue();
1492 else
1493 return emitError("invalid SSA value result number");
1494 consumeToken(Token::hash_identifier);
1495 }
1496
Chris Lattner7f9cc272018-07-19 08:35:28 -07001497 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001498}
1499
1500/// Parse a (possibly empty) list of SSA operands.
1501///
1502/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1503/// ssa-use-list-opt ::= ssa-use-list?
1504///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001505ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001506FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001507 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001508 return ParseSuccess;
1509 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001510 SSAUseInfo result;
1511 if (parseSSAUse(result))
1512 return ParseFailure;
1513 results.push_back(result);
1514 return ParseSuccess;
1515 });
Chris Lattner78276e32018-07-07 15:48:26 -07001516}
1517
1518/// Parse an SSA use with an associated type.
1519///
1520/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001521template <typename ResultType>
1522ResultType FunctionParser::parseSSADefOrUseAndType(
1523 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001524
Chris Lattnerf7702a62018-07-23 17:30:01 -07001525 SSAUseInfo useInfo;
1526 if (parseSSAUse(useInfo) ||
1527 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1528 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001529
Chris Lattner7f9cc272018-07-19 08:35:28 -07001530 auto *type = parseType();
1531 if (!type)
1532 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001533
James Molloy61a656c2018-07-22 15:45:24 -07001534 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001535}
1536
Chris Lattner2c402672018-07-23 11:56:17 -07001537/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1538/// followed by a type list. If hasParens is true, then the operands are
1539/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001540///
Chris Lattner2c402672018-07-23 11:56:17 -07001541/// ssa-use-and-type-list[parens]
1542/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1543///
1544/// ssa-use-and-type-list[!parens]
1545/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001546///
Chris Lattner40746442018-07-21 14:32:09 -07001547template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001548ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001549 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1550
1551 // If we are in the parenthesized form and no paren exists, then we succeed
1552 // with an empty list.
1553 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001554 return ParseSuccess;
1555
Chris Lattner2c402672018-07-23 11:56:17 -07001556 SmallVector<SSAUseInfo, 4> valueIDs;
1557 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001558 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001559
1560 if (isParenthesized && !consumeIf(Token::r_paren))
1561 return emitError("expected ')' in operand list");
1562
1563 // If there were no operands, then there is no colon or type lists.
1564 if (valueIDs.empty())
1565 return ParseSuccess;
1566
Chris Lattner2c402672018-07-23 11:56:17 -07001567 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001568 if (parseToken(Token::colon, "expected ':' in operand list") ||
1569 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001570 return ParseFailure;
1571
1572 if (valueIDs.size() != types.size())
1573 return emitError("expected " + Twine(valueIDs.size()) +
1574 " types to match operand list");
1575
1576 results.reserve(valueIDs.size());
1577 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1578 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1579 results.push_back(cast<ValueTy>(value));
1580 else
1581 return ParseFailure;
1582 }
1583
1584 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001585}
1586
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001587/// Parse the CFG or MLFunc operation.
1588///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001589/// operation ::=
1590/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1591/// `:` function-type
1592///
1593ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001594FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001595 auto loc = getToken().getLoc();
1596
1597 StringRef resultID;
1598 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001599 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001600 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001601 if (parseToken(Token::equal, "expected '=' after SSA name"))
1602 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001603 }
1604
Chris Lattner85ee1512018-07-25 11:15:20 -07001605 Operation *op;
1606 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1607 op = parseCustomOperation(createOpFunc);
1608 else if (getToken().is(Token::string))
1609 op = parseVerboseOperation(createOpFunc);
1610 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001611 return emitError("expected operation name in quotes");
1612
Chris Lattner85ee1512018-07-25 11:15:20 -07001613 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001614 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001615 return ParseFailure;
1616
1617 // We just parsed an operation. If it is a recognized one, verify that it
1618 // is structurally as we expect. If not, produce an error with a reasonable
1619 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001620 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001621 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001622 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001623 }
1624
Chris Lattner7f9cc272018-07-19 08:35:28 -07001625 // If the instruction had a name, register it.
1626 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001627 if (op->getNumResults() == 0)
1628 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001629
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001630 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001631 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1632 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001633 }
1634
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001635 return ParseSuccess;
1636}
Chris Lattnere79379a2018-06-22 10:39:19 -07001637
Chris Lattner85ee1512018-07-25 11:15:20 -07001638Operation *FunctionParser::parseVerboseOperation(
1639 const CreateOperationFunction &createOpFunc) {
Chris Lattner1628fa02018-08-23 14:32:25 -07001640
1641 // Get location information for the operation.
1642 auto *srcLocation = getEncodedSourceLocation(getToken().getLoc());
1643
Chris Lattner85ee1512018-07-25 11:15:20 -07001644 auto name = getToken().getStringValue();
1645 if (name.empty())
1646 return (emitError("empty operation name is invalid"), nullptr);
1647
1648 consumeToken(Token::string);
1649
Chris Lattner1628fa02018-08-23 14:32:25 -07001650 OperationState result(builder.getContext(), srcLocation, name);
Chris Lattner992a1272018-08-07 12:02:37 -07001651
Chris Lattner85ee1512018-07-25 11:15:20 -07001652 // Parse the operand list.
1653 SmallVector<SSAUseInfo, 8> operandInfos;
1654
1655 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1656 parseOptionalSSAUseList(operandInfos) ||
1657 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1658 return nullptr;
1659 }
1660
Chris Lattner85ee1512018-07-25 11:15:20 -07001661 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001662 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001663 return nullptr;
1664 }
1665
1666 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1667 return nullptr;
1668
1669 auto typeLoc = getToken().getLoc();
1670 auto type = parseType();
1671 if (!type)
1672 return nullptr;
1673 auto fnType = dyn_cast<FunctionType>(type);
1674 if (!fnType)
1675 return (emitError(typeLoc, "expected function type"), nullptr);
1676
Chris Lattner1eb77482018-08-22 19:25:49 -07001677 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001678
Chris Lattner85ee1512018-07-25 11:15:20 -07001679 // Check that we have the right number of types for the operands.
1680 auto operandTypes = fnType->getInputs();
1681 if (operandTypes.size() != operandInfos.size()) {
1682 auto plural = "s"[operandInfos.size() == 1];
1683 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1684 " operand type" + plural + " but had " +
1685 llvm::utostr(operandTypes.size())),
1686 nullptr);
1687 }
1688
1689 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001690 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001691 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1692 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001693 return nullptr;
1694 }
1695
Chris Lattner992a1272018-08-07 12:02:37 -07001696 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001697}
1698
1699namespace {
1700class CustomOpAsmParser : public OpAsmParser {
1701public:
1702 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1703 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1704
Chris Lattner85ee1512018-07-25 11:15:20 -07001705 //===--------------------------------------------------------------------===//
1706 // High level parsing methods.
1707 //===--------------------------------------------------------------------===//
1708
Chris Lattner1aa46322018-08-21 17:55:22 -07001709 bool getCurrentLocation(llvm::SMLoc *loc) override {
1710 *loc = parser.getToken().getLoc();
1711 return false;
1712 }
Chris Lattner091a6b52018-08-23 14:58:27 -07001713 bool parseComma() override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001714 return parser.parseToken(Token::comma, "expected ','");
1715 }
1716
Chris Lattner091a6b52018-08-23 14:58:27 -07001717 bool parseColonType(Type *&result) override {
1718 return parser.parseToken(Token::colon, "expected ':'") ||
1719 !(result = parser.parseType());
Chris Lattner85ee1512018-07-25 11:15:20 -07001720 }
1721
Chris Lattner091a6b52018-08-23 14:58:27 -07001722 bool parseColonTypeList(SmallVectorImpl<Type *> &result) override {
1723 if (parser.parseToken(Token::colon, "expected ':'"))
Chris Lattner85ee1512018-07-25 11:15:20 -07001724 return true;
1725
1726 do {
1727 if (auto *type = parser.parseType())
1728 result.push_back(type);
1729 else
1730 return true;
1731
1732 } while (parser.consumeIf(Token::comma));
1733 return false;
1734 }
1735
Chris Lattner85cf26d2018-08-02 16:54:36 -07001736 /// Parse an arbitrary attribute and return it in result. This also adds the
1737 /// attribute to the specified attribute list with the specified name. this
1738 /// captures the location of the attribute in 'loc' if it is non-null.
1739 bool parseAttribute(Attribute *&result, const char *attrName,
Chris Lattner091a6b52018-08-23 14:58:27 -07001740 SmallVectorImpl<NamedAttribute> &attrs) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001741 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001742 if (!result)
1743 return true;
1744
1745 attrs.push_back(
1746 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1747 return false;
1748 }
1749
1750 /// If a named attribute list is present, parse is into result.
Chris Lattner091a6b52018-08-23 14:58:27 -07001751 bool
1752 parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result) override {
Chris Lattner85cf26d2018-08-02 16:54:36 -07001753 if (parser.getToken().isNot(Token::l_brace))
1754 return false;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001755 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001756 }
1757
Chris Lattner1aa46322018-08-21 17:55:22 -07001758 /// Parse a function name like '@foo' and return the name in a form that can
1759 /// be passed to resolveFunctionName when a function type is available.
1760 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1761 loc = parser.getToken().getLoc();
1762
1763 if (parser.getToken().isNot(Token::at_identifier))
1764 return emitError(loc, "expected function name");
1765
1766 result = parser.getTokenSpelling();
1767 parser.consumeToken(Token::at_identifier);
1768 return false;
1769 }
1770
Chris Lattner85ee1512018-07-25 11:15:20 -07001771 bool parseOperand(OperandType &result) override {
1772 FunctionParser::SSAUseInfo useInfo;
1773 if (parser.parseSSAUse(useInfo))
1774 return true;
1775
1776 result = {useInfo.loc, useInfo.name, useInfo.number};
1777 return false;
1778 }
1779
1780 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1781 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001782 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001783 auto startLoc = parser.getToken().getLoc();
1784
Chris Lattner85cf26d2018-08-02 16:54:36 -07001785 // Handle delimiters.
1786 switch (delimiter) {
1787 case Delimiter::None:
Jacques Pienaar290a5012018-09-09 17:59:22 -07001788 // Don't check for the absence of a delimiter if the number of operands
1789 // is unknown (and hence the operand list could be empty).
1790 if (requiredOperandCount == -1)
1791 break;
1792 // Token already matches an identifier and so can't be a delimiter.
1793 if (parser.getToken().is(Token::percent_identifier))
1794 break;
1795 // Test against known delimiters.
1796 if (parser.getToken().is(Token::l_paren) ||
1797 parser.getToken().is(Token::l_square))
1798 return emitError(startLoc, "unexpected delimiter");
1799 return emitError(startLoc, "unable to parse '" +
1800 parser.getTokenSpelling() +
1801 "' as operand");
Chris Lattner85cf26d2018-08-02 16:54:36 -07001802 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001803 if (parser.getToken().isNot(Token::l_paren))
1804 return false;
1805 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001806 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001807 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1808 return true;
1809 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001810 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001811 if (parser.getToken().isNot(Token::l_square))
1812 return false;
1813 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001814 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001815 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1816 return true;
1817 break;
1818 }
1819
1820 // Check for zero operands.
1821 if (parser.getToken().is(Token::percent_identifier)) {
1822 do {
1823 OperandType operand;
1824 if (parseOperand(operand))
1825 return true;
1826 result.push_back(operand);
1827 } while (parser.consumeIf(Token::comma));
1828 }
1829
Chris Lattner85cf26d2018-08-02 16:54:36 -07001830 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001831 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001832 switch (delimiter) {
1833 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001834 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001835 case Delimiter::OptionalParen:
1836 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001837 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1838 return true;
1839 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001840 case Delimiter::OptionalSquare:
1841 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001842 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1843 return true;
1844 break;
1845 }
1846
1847 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
Jacques Pienaar79887452018-09-09 13:41:19 -07001848 return emitError(startLoc,
1849 "expected " + Twine(requiredOperandCount) + " operands");
Chris Lattner85ee1512018-07-25 11:15:20 -07001850 return false;
1851 }
1852
Chris Lattner1aa46322018-08-21 17:55:22 -07001853 /// Resolve a parse function name and a type into a function reference.
1854 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1855 llvm::SMLoc loc, Function *&result) {
1856 result = parser.resolveFunctionReference(name, loc, type);
1857 return result == nullptr;
1858 }
1859
Chris Lattner85ee1512018-07-25 11:15:20 -07001860 //===--------------------------------------------------------------------===//
1861 // Methods for interacting with the parser
1862 //===--------------------------------------------------------------------===//
1863
1864 Builder &getBuilder() const override { return parser.builder; }
1865
1866 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1867
Chris Lattner1aa46322018-08-21 17:55:22 -07001868 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001869 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001870 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1871 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001872 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1873 result.push_back(value);
1874 return false;
1875 }
1876 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001877 }
1878
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001879 /// Emit a diagnostic at the specified location and return true.
1880 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001881 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1882 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001883 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001884 }
1885
1886 bool didEmitError() const { return emittedError; }
1887
1888private:
1889 SMLoc nameLoc;
1890 StringRef opName;
1891 FunctionParser &parser;
1892 bool emittedError = false;
1893};
1894} // end anonymous namespace.
1895
1896Operation *FunctionParser::parseCustomOperation(
1897 const CreateOperationFunction &createOpFunc) {
1898 auto opLoc = getToken().getLoc();
1899 auto opName = getTokenSpelling();
1900 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1901
1902 auto *opDefinition = getOperationSet().lookup(opName);
1903 if (!opDefinition) {
1904 opAsmParser.emitError(opLoc, "is unknown");
1905 return nullptr;
1906 }
1907
1908 consumeToken();
1909
Chris Lattner1aa46322018-08-21 17:55:22 -07001910 // If the custom op parser crashes, produce some indication to help debugging.
1911 std::string opNameStr = opName.str();
1912 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1913 opNameStr.c_str());
1914
Chris Lattner1628fa02018-08-23 14:32:25 -07001915 // Get location information for the operation.
1916 auto *srcLocation = getEncodedSourceLocation(opLoc);
1917
Chris Lattner85ee1512018-07-25 11:15:20 -07001918 // Have the op implementation take a crack and parsing this.
Chris Lattner1628fa02018-08-23 14:32:25 -07001919 OperationState opState(builder.getContext(), srcLocation, opName);
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001920 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1921 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001922
1923 // If it emitted an error, we failed.
1924 if (opAsmParser.didEmitError())
1925 return nullptr;
1926
1927 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001928 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001929}
1930
Chris Lattner48af7d12018-07-09 19:05:38 -07001931//===----------------------------------------------------------------------===//
1932// CFG Functions
1933//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001934
Chris Lattner4c95a502018-06-23 16:03:42 -07001935namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001936/// This is a specialized parser for CFGFunction's, maintaining the state
1937/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001938class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001939public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001940 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001941 : FunctionParser(state, Kind::CFGFunc), function(function),
1942 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001943
1944 ParseResult parseFunctionBody();
1945
1946private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001947 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001948 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001949
1950 /// This builder intentionally shadows the builder in the base class, with a
1951 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001952 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001953
Chris Lattner4c95a502018-06-23 16:03:42 -07001954 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001955 /// already exist. The location specified is the point of use, which allows
1956 /// us to diagnose references to blocks that are not defined precisely.
1957 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1958 auto &blockAndLoc = blocksByName[name];
1959 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001960 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001961 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001962 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001963 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001964 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001965
James Molloy61a656c2018-07-22 15:45:24 -07001966 ParseResult
1967 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1968 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001969 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1970 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001971
Chris Lattner48af7d12018-07-09 19:05:38 -07001972 ParseResult parseBasicBlock();
Chris Lattner48af7d12018-07-09 19:05:38 -07001973 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001974};
1975} // end anonymous namespace
1976
James Molloy61a656c2018-07-22 15:45:24 -07001977/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001978/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001979///
1980/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1981///
1982ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1983 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1984 if (getToken().is(Token::r_brace))
1985 return ParseSuccess;
1986
1987 return parseCommaSeparatedList([&]() -> ParseResult {
1988 auto type = parseSSADefOrUseAndType<Type *>(
1989 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1990 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001991 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001992 return nullptr;
1993 return type;
1994 });
1995 return type ? ParseSuccess : ParseFailure;
1996 });
1997}
1998
Chris Lattner48af7d12018-07-09 19:05:38 -07001999ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002000 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002001 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
2002 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07002003
2004 // Make sure we have at least one block.
2005 if (getToken().is(Token::r_brace))
2006 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07002007
2008 // Parse the list of blocks.
2009 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07002010 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07002011 return ParseFailure;
2012
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002013 // Verify that all referenced blocks were defined. Iteration over a
2014 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002015 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002016 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002017 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002018 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002019 "reference to an undefined basic block '" + elt.first() +
2020 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002021 }
2022
Chris Lattner40746442018-07-21 14:32:09 -07002023 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002024}
2025
2026/// Basic block declaration.
2027///
2028/// basic-block ::= bb-label instruction* terminator-stmt
2029/// bb-label ::= bb-id bb-arg-list? `:`
2030/// bb-id ::= bare-id
2031/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2032///
Chris Lattner48af7d12018-07-09 19:05:38 -07002033ParseResult CFGFunctionParser::parseBasicBlock() {
2034 SMLoc nameLoc = getToken().getLoc();
2035 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002036 if (parseToken(Token::bare_identifier, "expected basic block name"))
2037 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002038
Chris Lattner48af7d12018-07-09 19:05:38 -07002039 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002040
2041 // If this block has already been parsed, then this is a redefinition with the
2042 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002043 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002044 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2045
Chris Lattner78276e32018-07-07 15:48:26 -07002046 // If an argument list is present, parse it.
2047 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002048 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002049 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2050 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002051 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002052 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002053
James Molloy61a656c2018-07-22 15:45:24 -07002054 // Add the block to the function.
2055 function->push_back(block);
2056
Chris Lattnerf7702a62018-07-23 17:30:01 -07002057 if (parseToken(Token::colon, "expected ':' after basic block name"))
2058 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002059
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002060 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002061 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002062
Chris Lattner992a1272018-08-07 12:02:37 -07002063 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2064 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002065 };
2066
Chris Lattnered65a732018-06-28 20:45:33 -07002067 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002068 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002069 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002070 return ParseFailure;
2071 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002072
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002073 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002074 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002075
2076 return ParseSuccess;
2077}
2078
James Molloy4f788372018-07-24 15:01:27 -07002079ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2080 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2081 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2082 if (parseToken(Token::bare_identifier, "expected basic block name"))
2083 return ParseFailure;
2084
2085 if (!consumeIf(Token::l_paren))
2086 return ParseSuccess;
2087 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2088 parseToken(Token::r_paren, "expected ')' to close argument list"))
2089 return ParseFailure;
2090 return ParseSuccess;
2091}
2092
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002093/// Parse the terminator instruction for a basic block.
2094///
2095/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002096/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002097/// terminator-stmt ::=
2098/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2099/// terminator-stmt ::= `return` ssa-use-and-type-list?
2100///
Chris Lattner48af7d12018-07-09 19:05:38 -07002101TerminatorInst *CFGFunctionParser::parseTerminator() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002102 auto loc = getToken().getLoc();
2103
Chris Lattner48af7d12018-07-09 19:05:38 -07002104 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002105 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002106 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002107
Chris Lattner40746442018-07-21 14:32:09 -07002108 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002109 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002110
Chris Lattner2c402672018-07-23 11:56:17 -07002111 // Parse any operands.
2112 SmallVector<CFGValue *, 8> operands;
2113 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2114 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002115 return builder.createReturn(getEncodedSourceLocation(loc), operands);
Chris Lattner40746442018-07-21 14:32:09 -07002116 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002117
2118 case Token::kw_br: {
2119 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002120 BasicBlock *destBB;
2121 SmallVector<CFGValue *, 4> values;
2122 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002123 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002124 auto branch = builder.createBranch(getEncodedSourceLocation(loc), destBB);
James Molloy4f788372018-07-24 15:01:27 -07002125 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002126 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002127 }
James Molloy4f788372018-07-24 15:01:27 -07002128
2129 case Token::kw_cond_br: {
2130 consumeToken(Token::kw_cond_br);
2131 SSAUseInfo ssaUse;
2132 if (parseSSAUse(ssaUse))
2133 return nullptr;
2134 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2135 if (!cond)
2136 return (emitError("expected type was boolean (i1)"), nullptr);
2137 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2138 return nullptr;
2139
2140 BasicBlock *trueBlock;
2141 SmallVector<CFGValue *, 4> trueOperands;
2142 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2143 return nullptr;
2144
2145 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2146 return nullptr;
2147
2148 BasicBlock *falseBlock;
2149 SmallVector<CFGValue *, 4> falseOperands;
2150 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2151 return nullptr;
2152
Chris Lattner091a6b52018-08-23 14:58:27 -07002153 auto branch =
2154 builder.createCondBranch(getEncodedSourceLocation(loc),
2155 cast<CFGValue>(cond), trueBlock, falseBlock);
James Molloy4f788372018-07-24 15:01:27 -07002156 branch->addTrueOperands(trueOperands);
2157 branch->addFalseOperands(falseOperands);
2158 return branch;
2159 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002160 }
2161}
2162
Chris Lattner48af7d12018-07-09 19:05:38 -07002163//===----------------------------------------------------------------------===//
2164// ML Functions
2165//===----------------------------------------------------------------------===//
2166
2167namespace {
2168/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002169class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002170public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002171 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002172 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002173 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002174
2175 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002176
2177private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002178 MLFunction *function;
2179
2180 /// This builder intentionally shadows the builder in the base class, with a
2181 /// more specific builder type.
2182 MLFuncBuilder builder;
2183
2184 ParseResult parseForStmt();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002185 ParseResult parseIntConstant(int64_t &val);
2186 ParseResult parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002187 unsigned numDims, unsigned numOperands,
2188 const char *affineStructName);
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002189 ParseResult parseBound(SmallVectorImpl<MLValue *> &operands, AffineMap *&map,
2190 bool isLower);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002191 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002192 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002193 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002194 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002195};
2196} // end anonymous namespace
2197
Chris Lattner48af7d12018-07-09 19:05:38 -07002198ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002199 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002200
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002201 // Parse statements in this function.
2202 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002203 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002204
Chris Lattner40746442018-07-21 14:32:09 -07002205 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002206}
2207
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002208/// For statement.
2209///
Chris Lattner48af7d12018-07-09 19:05:38 -07002210/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2211/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002212///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002214 consumeToken(Token::kw_for);
2215
Uday Bondhugula67701712018-08-21 16:01:23 -07002216 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002217 if (getToken().isNot(Token::percent_identifier))
2218 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002219
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002220 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002221 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002222 consumeToken(Token::percent_identifier);
2223
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002224 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002225 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002226
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002227 // Parse lower bound.
2228 SmallVector<MLValue *, 4> lbOperands;
2229 AffineMap *lbMap = nullptr;
2230 if (parseBound(lbOperands, lbMap, /*isLower*/ true))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002231 return ParseFailure;
2232
Chris Lattnerf7702a62018-07-23 17:30:01 -07002233 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2234 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002235
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002236 // Parse upper bound.
2237 SmallVector<MLValue *, 4> ubOperands;
2238 AffineMap *ubMap = nullptr;
2239 if (parseBound(ubOperands, ubMap, /*isLower*/ false))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002240 return ParseFailure;
2241
Uday Bondhugula67701712018-08-21 16:01:23 -07002242 // Parse step.
2243 int64_t step = 1;
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002244 if (consumeIf(Token::kw_step) && parseIntConstant(step))
2245 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002246
2247 // Create for statement.
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002248 ForStmt *forStmt =
2249 builder.createFor(getEncodedSourceLocation(loc), lbOperands, lbMap,
2250 ubOperands, ubMap, step);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002251
2252 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002253 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2254 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002255
2256 // If parsing of the for statement body fails,
2257 // MLIR contains for statement with those nested statements that have been
2258 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002259 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002260 return ParseFailure;
2261
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002262 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002263 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002264
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002265 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002266}
2267
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002268/// Parse integer constant as affine constant expression.
2269ParseResult MLFunctionParser::parseIntConstant(int64_t &val) {
2270 bool negate = consumeIf(Token::minus);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002271
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002272 if (getToken().isNot(Token::integer))
2273 return emitError("expected integer");
2274
2275 auto uval = getToken().getUInt64IntegerValue();
2276
2277 if (!uval.hasValue() || (int64_t)uval.getValue() < 0) {
2278 return emitError("bound or step is too large for affineint");
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002279 }
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002280
2281 val = (int64_t)uval.getValue();
2282 if (negate)
2283 val = -val;
2284 consumeToken();
2285
2286 return ParseSuccess;
2287}
2288
2289/// Dimensions and symbol use list.
2290///
2291/// dim-use-list ::= `(` ssa-use-list? `)`
2292/// symbol-use-list ::= `[` ssa-use-list? `]`
2293/// dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
2294///
2295ParseResult
2296MLFunctionParser::parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002297 unsigned numDims, unsigned numOperands,
2298 const char *affineStructName) {
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002299 if (parseToken(Token::l_paren, "expected '('"))
2300 return ParseFailure;
2301
2302 SmallVector<SSAUseInfo, 4> opInfo;
2303 parseOptionalSSAUseList(opInfo);
2304
2305 if (parseToken(Token::r_paren, "expected ')'"))
2306 return ParseFailure;
2307
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002308 if (numDims != opInfo.size())
2309 return emitError("dim operand count and " + Twine(affineStructName) +
2310 " dim count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002311
2312 if (consumeIf(Token::l_square)) {
2313 parseOptionalSSAUseList(opInfo);
2314 if (parseToken(Token::r_square, "expected ']'"))
2315 return ParseFailure;
2316 }
2317
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002318 if (numOperands != opInfo.size())
2319 return emitError("symbol operand count and " + Twine(affineStructName) +
2320 " symbol count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002321
2322 // Resolve SSA uses.
2323 Type *affineIntType = builder.getAffineIntType();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002324 for (unsigned i = 0, e = opInfo.size(); i != e; ++i) {
2325 SSAValue *sval = resolveSSAUse(opInfo[i], affineIntType);
2326 if (!sval)
2327 return ParseFailure;
2328
2329 auto *v = cast<MLValue>(sval);
2330 if (i < numDims && !v->isValidDim())
2331 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002332 "' cannot be used as a dimension id");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002333 if (i >= numDims && !v->isValidSymbol())
2334 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002335 "' cannot be used as a symbol");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002336 operands.push_back(v);
2337 }
2338
2339 return ParseSuccess;
2340}
2341
2342// Loop bound.
2343///
2344/// lower-bound ::= `max`? affine-map dim-and-symbol-use-list | shorthand-bound
2345/// upper-bound ::= `min`? affine-map dim-and-symbol-use-list | shorthand-bound
2346/// shorthand-bound ::= ssa-id | `-`? integer-literal
2347///
2348ParseResult MLFunctionParser::parseBound(SmallVectorImpl<MLValue *> &operands,
2349 AffineMap *&map, bool isLower) {
2350 // 'min' / 'max' prefixes are syntactic sugar. Ignore them.
2351 if (isLower)
2352 consumeIf(Token::kw_max);
2353 else
2354 consumeIf(Token::kw_min);
2355
2356 // Parse full form - affine map followed by dim and symbol list.
2357 if (getToken().isAny(Token::hash_identifier, Token::l_paren)) {
2358 map = parseAffineMapReference();
2359 if (!map)
2360 return ParseFailure;
2361
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002362 if (parseDimAndSymbolList(operands, map->getNumDims(),
2363 map->getNumOperands(), "affine map"))
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002364 return ParseFailure;
2365 return ParseSuccess;
2366 }
2367
2368 // Parse shorthand form.
2369 if (getToken().isAny(Token::minus, Token::integer)) {
2370 int64_t val;
2371 if (!parseIntConstant(val)) {
2372 map = builder.getConstantMap(val);
2373 return ParseSuccess;
2374 }
2375 return ParseFailure;
2376 }
2377
2378 // Parse ssa-id as identity map.
2379 SSAUseInfo opInfo;
2380 if (parseSSAUse(opInfo))
2381 return ParseFailure;
2382
2383 // TODO: improve error message when SSA value is not an affine integer.
2384 // Currently it is 'use of value ... expects different type than prior uses'
2385 if (auto *value = resolveSSAUse(opInfo, builder.getAffineIntType()))
2386 operands.push_back(cast<MLValue>(value));
2387 else
2388 return ParseFailure;
2389
2390 // Create an identity map using dim id for an induction variable and
2391 // symbol otherwise. This representation is optimized for storage.
2392 // Analysis passes may expand it into a multi-dimensional map if desired.
2393 if (isa<ForStmt>(operands[0]))
2394 map = builder.getDimIdentityMap();
2395 else
2396 map = builder.getSymbolIdentityMap();
2397
2398 return ParseSuccess;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002399}
2400
Uday Bondhugulabc535622018-08-07 14:24:38 -07002401/// Parse an affine constraint.
2402/// affine-constraint ::= affine-expr `>=` `0`
2403/// | affine-expr `==` `0`
2404///
2405/// isEq is set to true if the parsed constraint is an equality, false if it is
2406/// an inequality (greater than or equal).
2407///
2408AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2409 AffineExpr *expr = parseAffineExpr();
2410 if (!expr)
2411 return nullptr;
2412
2413 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2414 getToken().is(Token::integer)) {
2415 auto dim = getToken().getUnsignedIntegerValue();
2416 if (dim.hasValue() && dim.getValue() == 0) {
2417 consumeToken(Token::integer);
2418 *isEq = false;
2419 return expr;
2420 }
2421 return (emitError("expected '0' after '>='"), nullptr);
2422 }
2423
2424 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2425 getToken().is(Token::integer)) {
2426 auto dim = getToken().getUnsignedIntegerValue();
2427 if (dim.hasValue() && dim.getValue() == 0) {
2428 consumeToken(Token::integer);
2429 *isEq = true;
2430 return expr;
2431 }
2432 return (emitError("expected '0' after '=='"), nullptr);
2433 }
2434
2435 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2436 nullptr);
2437}
2438
2439/// Parse an integer set definition.
2440/// integer-set-inline
2441/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2442/// affine-constraint-conjunction ::= /*empty*/
2443/// | affine-constraint (`,` affine-constraint)*
2444///
2445IntegerSet *AffineParser::parseIntegerSetInline() {
2446 unsigned numDims = 0, numSymbols = 0;
2447
2448 // List of dimensional identifiers.
2449 if (parseDimIdList(numDims))
2450 return nullptr;
2451
2452 // Symbols are optional.
2453 if (getToken().is(Token::l_square)) {
2454 if (parseSymbolIdList(numSymbols))
2455 return nullptr;
2456 }
2457
2458 if (parseToken(Token::colon, "expected ':' or '['") ||
2459 parseToken(Token::l_paren,
2460 "expected '(' at start of integer set constraint list"))
2461 return nullptr;
2462
2463 SmallVector<AffineExpr *, 4> constraints;
2464 SmallVector<bool, 4> isEqs;
2465 auto parseElt = [&]() -> ParseResult {
2466 bool isEq;
2467 auto *elt = parseAffineConstraint(&isEq);
2468 ParseResult res = elt ? ParseSuccess : ParseFailure;
2469 if (elt) {
2470 constraints.push_back(elt);
2471 isEqs.push_back(isEq);
2472 }
2473 return res;
2474 };
2475
2476 // Parse a list of affine constraints (comma-separated) .
2477 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2478 // affine-constraint)* `)
2479 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2480 return nullptr;
2481
2482 // Parsed a valid integer set.
2483 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2484}
2485
2486IntegerSet *Parser::parseIntegerSetInline() {
2487 return AffineParser(state).parseIntegerSetInline();
2488}
2489
2490/// Parse a reference to an integer set.
2491/// integer-set ::= integer-set-id | integer-set-inline
2492/// integer-set-id ::= `@@` suffix-id
2493///
2494IntegerSet *Parser::parseIntegerSetReference() {
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002495 // TODO: change '@@' integer set prefix to '#'.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002496 if (getToken().is(Token::double_at_identifier)) {
2497 // Parse integer set identifier and verify that it exists.
2498 StringRef integerSetId = getTokenSpelling().drop_front(2);
2499 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2500 return (emitError("undefined integer set id '" + integerSetId + "'"),
2501 nullptr);
2502 consumeToken(Token::double_at_identifier);
2503 return getState().integerSetDefinitions[integerSetId];
2504 }
2505 // Try to parse an inline integer set definition.
2506 return parseIntegerSetInline();
2507}
2508
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002509/// If statement.
2510///
Chris Lattner48af7d12018-07-09 19:05:38 -07002511/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2512/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2513/// ml-if-stmt ::= ml-if-head
2514/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002515///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002516ParseResult MLFunctionParser::parseIfStmt() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002517 auto loc = getToken().getLoc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002518 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002519
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002520 IntegerSet *set = parseIntegerSetReference();
2521 if (!set)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002522 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002523
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002524 SmallVector<MLValue *, 4> operands;
2525 if (parseDimAndSymbolList(operands, set->getNumDims(), set->getNumOperands(),
2526 "integer set"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002527 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002528
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002529 IfStmt *ifStmt =
2530 builder.createIf(getEncodedSourceLocation(loc), operands, set);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002531
Chris Lattnere787b322018-08-08 11:14:57 -07002532 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002533
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002534 // When parsing of an if statement body fails, the IR contains
2535 // the if statement with the portion of the body that has been
2536 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002537 if (parseStmtBlock(thenClause))
2538 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002539
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002540 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002541 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002542 if (parseElseClause(elseClause))
2543 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002544 }
2545
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002546 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002547 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002548
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002549 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002550}
2551
2552ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2553 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002554 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002555 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002556 }
2557
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002558 return parseStmtBlock(elseClause);
2559}
2560
2561///
2562/// Parse a list of statements ending with `return` or `}`
2563///
2564ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002565 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2566 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002567 };
2568
Chris Lattnere787b322018-08-08 11:14:57 -07002569 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002570
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002571 // Parse statements till we see '}' or 'return'.
2572 // Return statement is parsed separately to emit a more intuitive error
2573 // when '}' is missing after the return statement.
2574 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002575 switch (getToken().getKind()) {
2576 default:
2577 if (parseOperation(createOpFunc))
2578 return ParseFailure;
2579 break;
2580 case Token::kw_for:
2581 if (parseForStmt())
2582 return ParseFailure;
2583 break;
2584 case Token::kw_if:
2585 if (parseIfStmt())
2586 return ParseFailure;
2587 break;
2588 } // end switch
2589 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002590
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002591 // Parse the return statement.
2592 if (getToken().is(Token::kw_return))
2593 if (parseOperation(createOpFunc))
2594 return ParseFailure;
2595
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002596 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002597}
2598
2599///
2600/// Parse `{` ml-stmt* `}`
2601///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002602ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002603 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2604 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002605 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002606 return ParseFailure;
2607
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002608 return ParseSuccess;
2609}
2610
Chris Lattner4c95a502018-06-23 16:03:42 -07002611//===----------------------------------------------------------------------===//
2612// Top-level entity parsing.
2613//===----------------------------------------------------------------------===//
2614
Chris Lattner2e595eb2018-07-10 10:08:27 -07002615namespace {
2616/// This parser handles entities that are only valid at the top level of the
2617/// file.
2618class ModuleParser : public Parser {
2619public:
2620 explicit ModuleParser(ParserState &state) : Parser(state) {}
2621
2622 ParseResult parseModule();
2623
2624private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002625 ParseResult finalizeModule();
2626
Chris Lattner2e595eb2018-07-10 10:08:27 -07002627 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002628 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002629
2630 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002631 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2632 SmallVectorImpl<StringRef> &argNames);
2633 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2634 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002635 ParseResult parseExtFunc();
2636 ParseResult parseCFGFunc();
2637 ParseResult parseMLFunc();
2638};
2639} // end anonymous namespace
2640
2641/// Affine map declaration.
2642///
2643/// affine-map-def ::= affine-map-id `=` affine-map-inline
2644///
2645ParseResult ModuleParser::parseAffineMapDef() {
2646 assert(getToken().is(Token::hash_identifier));
2647
2648 StringRef affineMapId = getTokenSpelling().drop_front();
2649
2650 // Check for redefinitions.
Nicolas Vasilache97298152018-08-27 10:10:42 -07002651 auto *&entry = getState().affineMapDefinitions[affineMapId];
2652 if (entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002653 return emitError("redefinition of affine map id '" + affineMapId + "'");
2654
2655 consumeToken(Token::hash_identifier);
2656
2657 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002658 if (parseToken(Token::equal,
2659 "expected '=' in affine map outlined definition"))
2660 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002661
Nicolas Vasilache97298152018-08-27 10:10:42 -07002662 entry = parseAffineMapInline();
2663 if (!entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002664 return ParseFailure;
2665
2666 return ParseSuccess;
2667}
2668
2669/// Integer set declaration.
2670///
2671/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2672///
2673ParseResult ModuleParser::parseIntegerSetDef() {
2674 assert(getToken().is(Token::double_at_identifier));
2675
2676 StringRef integerSetId = getTokenSpelling().drop_front(2);
2677
2678 // Check for redefinitions (a default entry is created if one doesn't exist)
Nicolas Vasilache97298152018-08-27 10:10:42 -07002679 auto *&entry = getState().integerSetDefinitions[integerSetId];
2680 if (entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002681 return emitError("redefinition of integer set id '" + integerSetId + "'");
2682
2683 consumeToken(Token::double_at_identifier);
2684
2685 // Parse the '='
2686 if (parseToken(Token::equal,
2687 "expected '=' in outlined integer set definition"))
2688 return ParseFailure;
2689
Nicolas Vasilache97298152018-08-27 10:10:42 -07002690 entry = parseIntegerSetInline();
2691 if (!entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002692 return ParseFailure;
2693
Chris Lattner2e595eb2018-07-10 10:08:27 -07002694 return ParseSuccess;
2695}
2696
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002697/// Parse a (possibly empty) list of MLFunction arguments with types.
2698///
2699/// ml-argument ::= ssa-id `:` type
2700/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2701///
2702ParseResult
2703ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2704 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002705 consumeToken(Token::l_paren);
2706
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002707 auto parseElt = [&]() -> ParseResult {
2708 // Parse argument name
2709 if (getToken().isNot(Token::percent_identifier))
2710 return emitError("expected SSA identifier");
2711
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002712 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002713 consumeToken(Token::percent_identifier);
2714 argNames.push_back(name);
2715
Chris Lattnerf7702a62018-07-23 17:30:01 -07002716 if (parseToken(Token::colon, "expected ':'"))
2717 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002718
2719 // Parse argument type
2720 auto elt = parseType();
2721 if (!elt)
2722 return ParseFailure;
2723 argTypes.push_back(elt);
2724
2725 return ParseSuccess;
2726 };
2727
Chris Lattner40746442018-07-21 14:32:09 -07002728 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002729}
2730
Chris Lattner2e595eb2018-07-10 10:08:27 -07002731/// Parse a function signature, starting with a name and including the parameter
2732/// list.
2733///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002734/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002735/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2736///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002737ParseResult
2738ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2739 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002740 if (getToken().isNot(Token::at_identifier))
2741 return emitError("expected a function identifier like '@foo'");
2742
2743 name = getTokenSpelling().drop_front();
2744 consumeToken(Token::at_identifier);
2745
2746 if (getToken().isNot(Token::l_paren))
2747 return emitError("expected '(' in function signature");
2748
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002749 SmallVector<Type *, 4> argTypes;
2750 ParseResult parseResult;
2751
2752 if (argNames)
2753 parseResult = parseMLArgumentList(argTypes, *argNames);
2754 else
2755 parseResult = parseTypeList(argTypes);
2756
2757 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002758 return ParseFailure;
2759
2760 // Parse the return type if present.
2761 SmallVector<Type *, 4> results;
2762 if (consumeIf(Token::arrow)) {
2763 if (parseTypeList(results))
2764 return ParseFailure;
2765 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002766 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002767 return ParseSuccess;
2768}
2769
2770/// External function declarations.
2771///
2772/// ext-func ::= `extfunc` function-signature
2773///
2774ParseResult ModuleParser::parseExtFunc() {
2775 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002776 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002777
2778 StringRef name;
2779 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002780 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002781 return ParseFailure;
2782
2783 // Okay, the external function definition was parsed correctly.
Chris Lattner791813d2018-09-07 09:08:13 -07002784 auto *function = new ExtFunction(getEncodedSourceLocation(loc), name, type);
Chris Lattner974a8762018-08-17 16:49:42 -07002785 getModule()->getFunctions().push_back(function);
2786
2787 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002788 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002789 return emitError(loc,
2790 "redefinition of function named '" + name.str() + "'");
2791
Chris Lattner2e595eb2018-07-10 10:08:27 -07002792 return ParseSuccess;
2793}
2794
2795/// CFG function declarations.
2796///
2797/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2798///
2799ParseResult ModuleParser::parseCFGFunc() {
2800 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002801 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002802
2803 StringRef name;
2804 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002805 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002806 return ParseFailure;
2807
2808 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner791813d2018-09-07 09:08:13 -07002809 auto *function = new CFGFunction(getEncodedSourceLocation(loc), name, type);
Chris Lattner974a8762018-08-17 16:49:42 -07002810 getModule()->getFunctions().push_back(function);
2811
2812 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002813 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002814 return emitError(loc,
2815 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002816
2817 return CFGFunctionParser(getState(), function).parseFunctionBody();
2818}
2819
2820/// ML function declarations.
2821///
2822/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2823///
2824ParseResult ModuleParser::parseMLFunc() {
2825 consumeToken(Token::kw_mlfunc);
2826
2827 StringRef name;
2828 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002829 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002830
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002831 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002832 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002833 return ParseFailure;
2834
2835 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner791813d2018-09-07 09:08:13 -07002836 auto *function =
2837 MLFunction::create(getEncodedSourceLocation(loc), name, type);
Chris Lattner974a8762018-08-17 16:49:42 -07002838 getModule()->getFunctions().push_back(function);
2839
2840 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002841 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002842 return emitError(loc,
2843 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002844
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002845 // Create the parser.
2846 auto parser = MLFunctionParser(getState(), function);
2847
2848 // Add definitions of the function arguments.
2849 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2850 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2851 return ParseFailure;
2852 }
2853
2854 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002855}
2856
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002857/// Given an attribute that could refer to a function attribute in the remapping
2858/// table, walk it and rewrite it to use the mapped function. If it doesn't
2859/// refer to anything in the table, then it is returned unmodified.
2860static Attribute *
2861remapFunctionAttrs(Attribute *input,
2862 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2863 MLIRContext *context) {
2864 // Most attributes are trivially unrelated to function attributes, skip them
2865 // rapidly.
2866 if (!input->isOrContainsFunction())
2867 return input;
2868
2869 // If we have a function attribute, remap it.
2870 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2871 auto it = remappingTable.find(fnAttr);
2872 return it != remappingTable.end() ? it->second : input;
2873 }
2874
2875 // Otherwise, we must have an array attribute, remap the elements.
2876 auto *arrayAttr = cast<ArrayAttr>(input);
2877 SmallVector<Attribute *, 8> remappedElts;
2878 bool anyChange = false;
2879 for (auto *elt : arrayAttr->getValue()) {
2880 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2881 remappedElts.push_back(newElt);
2882 anyChange |= (elt != newElt);
2883 }
2884
2885 if (!anyChange)
2886 return input;
2887
2888 return ArrayAttr::get(remappedElts, context);
2889}
2890
2891/// Remap function attributes to resolve forward references to their actual
2892/// definition.
2893static void remapFunctionAttrsInOperation(
2894 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2895 for (auto attr : op->getAttrs()) {
2896 // Do the remapping, if we got the same thing back, then it must contain
2897 // functions that aren't getting remapped.
2898 auto *newVal =
2899 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2900 if (newVal == attr.second)
2901 continue;
2902
2903 // Otherwise, replace the existing attribute with the new one. It is safe
2904 // to mutate the attribute list while we walk it because underlying
2905 // attribute lists are uniqued and immortal.
2906 op->setAttr(attr.first, newVal);
2907 }
2908}
2909
Chris Lattner4613d9e2018-08-19 21:17:22 -07002910/// Finish the end of module parsing - when the result is valid, do final
2911/// checking.
2912ParseResult ModuleParser::finalizeModule() {
2913
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002914 // Resolve all forward references, building a remapping table of attributes.
2915 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002916 for (auto forwardRef : getState().functionForwardRefs) {
2917 auto name = forwardRef.first;
2918
2919 // Resolve the reference.
2920 auto *resolvedFunction = getModule()->getNamedFunction(name);
Chris Lattner791813d2018-09-07 09:08:13 -07002921 if (!resolvedFunction) {
2922 forwardRef.second->emitError("reference to undefined function '" +
2923 name.str() + "'");
2924 return ParseFailure;
2925 }
Chris Lattner4613d9e2018-08-19 21:17:22 -07002926
Chris Lattner791813d2018-09-07 09:08:13 -07002927 remappingTable[builder.getFunctionAttr(forwardRef.second)] =
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002928 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002929 }
2930
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002931 // If there was nothing to remap, then we're done.
2932 if (remappingTable.empty())
2933 return ParseSuccess;
2934
2935 // Otherwise, walk the entire module replacing uses of one attribute set with
2936 // the correct ones.
2937 for (auto &fn : *getModule()) {
2938 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2939 for (auto &bb : *cfgFn) {
2940 for (auto &inst : bb) {
2941 remapFunctionAttrsInOperation(&inst, remappingTable);
2942 }
2943 }
2944 }
2945
2946 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2947 auto *mlFn = dyn_cast<MLFunction>(&fn);
2948 if (!mlFn)
2949 continue;
2950
2951 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2952 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2953 : remappingTable(remappingTable) {}
2954 void visitOperationStmt(OperationStmt *opStmt) {
2955 remapFunctionAttrsInOperation(opStmt, remappingTable);
2956 }
2957
2958 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2959 };
2960
2961 MLFnWalker(remappingTable).walk(mlFn);
2962 }
2963
2964 // Now that all references to the forward definition placeholders are
2965 // resolved, we can deallocate the placeholders.
2966 for (auto forwardRef : getState().functionForwardRefs)
Chris Lattner791813d2018-09-07 09:08:13 -07002967 forwardRef.second->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002968 return ParseSuccess;
2969}
2970
Chris Lattnere79379a2018-06-22 10:39:19 -07002971/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002972ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002973 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002974 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002975 default:
2976 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002977 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002978
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002979 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002980 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002981 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002982
2983 // If we got an error token, then the lexer already emitted an error, just
2984 // stop. Someday we could introduce error recovery if there was demand for
2985 // it.
2986 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002987 return ParseFailure;
2988
2989 case Token::hash_identifier:
2990 if (parseAffineMapDef())
2991 return ParseFailure;
2992 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002993
Uday Bondhugulabc535622018-08-07 14:24:38 -07002994 case Token::double_at_identifier:
2995 if (parseIntegerSetDef())
2996 return ParseFailure;
2997 break;
2998
Chris Lattnere79379a2018-06-22 10:39:19 -07002999 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003000 if (parseExtFunc())
3001 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07003002 break;
3003
Chris Lattner4c95a502018-06-23 16:03:42 -07003004 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003005 if (parseCFGFunc())
3006 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07003007 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07003008
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003009 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003010 if (parseMLFunc())
3011 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003012 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003013 }
3014 }
3015}
3016
3017//===----------------------------------------------------------------------===//
3018
3019/// This parses the file specified by the indicated SourceMgr and returns an
3020/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaardadee542018-09-08 18:37:27 -07003021Module *mlir::parseSourceFile(const llvm::SourceMgr &sourceMgr,
Chris Lattner7879f842018-09-02 22:01:45 -07003022 MLIRContext *context) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003023
Chris Lattner2e595eb2018-07-10 10:08:27 -07003024 // This is the result module we are parsing into.
3025 std::unique_ptr<Module> module(new Module(context));
3026
Chris Lattner7879f842018-09-02 22:01:45 -07003027 ParserState state(sourceMgr, module.get());
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003028 if (ModuleParser(state).parseModule()) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07003029 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003030 }
Chris Lattner21e67f62018-07-06 10:46:19 -07003031
3032 // Make sure the parse module has no other structural problems detected by the
3033 // verifier.
Chris Lattner791813d2018-09-07 09:08:13 -07003034 if (module->verify())
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003035 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003036
Chris Lattner2e595eb2018-07-10 10:08:27 -07003037 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07003038}
Jacques Pienaarbd22d432018-09-03 07:38:31 -07003039
3040/// This parses the program string to a MLIR module if it was valid. If not, it
3041/// emits diagnostics and returns null.
3042Module *mlir::parseSourceString(StringRef moduleStr, MLIRContext *context) {
3043 auto memBuffer = MemoryBuffer::getMemBuffer(moduleStr);
3044 if (!memBuffer)
3045 return nullptr;
3046
3047 SourceMgr sourceMgr;
3048 sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
3049 return parseSourceFile(sourceMgr, context);
3050}