blob: 71737cee10aed237e4f9d576866b52c9251baabf [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070030#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070032#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070033#include "mlir/IR/Types.h"
Chris Lattner6119d382018-07-20 18:41:34 -070034#include "llvm/ADT/DenseMap.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070035#include "llvm/Support/SourceMgr.h"
36using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070038using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070039
Chris Lattnerf7e22732018-06-22 22:03:48 -070040/// Simple enum to make code read better in cases that would otherwise return a
41/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070042enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattner48af7d12018-07-09 19:05:38 -070044namespace {
45class Parser;
46
47/// This class refers to all of the state maintained globally by the parser,
48/// such as the current lexer position etc. The Parser base class provides
49/// methods to access this.
50class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070051public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070052 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070053 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 : context(module->getContext()), module(module),
55 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070056 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
57 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070058
59 // A map from affine map identifier to AffineMap.
60 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070061
Chris Lattnere79379a2018-06-22 10:39:19 -070062private:
Chris Lattner48af7d12018-07-09 19:05:38 -070063 ParserState(const ParserState &) = delete;
64 void operator=(const ParserState &) = delete;
65
66 friend class Parser;
67
68 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070069 MLIRContext *const context;
70
71 // This is the module we are parsing into.
72 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070073
74 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070075 Lexer lex;
76
77 // This is the next token that hasn't been consumed yet.
78 Token curToken;
79
Jacques Pienaar9c411be2018-06-24 19:17:35 -070080 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070081 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -070082
83 // The active OperationSet we're parsing with.
84 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070085};
86} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070087
Chris Lattner48af7d12018-07-09 19:05:38 -070088namespace {
89
Chris Lattner7f9cc272018-07-19 08:35:28 -070090typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
91 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070092 CreateOperationFunction;
93
Chris Lattner48af7d12018-07-09 19:05:38 -070094/// This class implement support for parsing global entities like types and
95/// shared entities like SSA names. It is intended to be subclassed by
96/// specialized subparsers that include state, e.g. when a local symbol table.
97class Parser {
98public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700100
Chris Lattner2e595eb2018-07-10 10:08:27 -0700101 Parser(ParserState &state) : builder(state.context), state(state) {}
102
103 // Helper methods to get stuff from the parser-global state.
104 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700105 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700106 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700107 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700108
109 /// Return the current token the parser is inspecting.
110 const Token &getToken() const { return state.curToken; }
111 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700112
113 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700114 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700115 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700116 }
117 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700118
119 /// Advance the current lexer onto the next token.
120 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700121 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700122 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700123 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700124 }
125
126 /// Advance the current lexer onto the next token, asserting what the expected
127 /// current token is. This is preferred to the above method because it leads
128 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700129 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700130 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700131 consumeToken();
132 }
133
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700134 /// If the current token has the specified kind, consume it and return true.
135 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700136 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700137 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700138 return false;
139 consumeToken(kind);
140 return true;
141 }
142
Chris Lattnerf7702a62018-07-23 17:30:01 -0700143 /// Consume the specified token if present and return success. On failure,
144 /// output a diagnostic and return failure.
145 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
146
Chris Lattner40746442018-07-21 14:32:09 -0700147 /// Parse a comma-separated list of elements up until the specified end token.
148 ParseResult
149 parseCommaSeparatedListUntil(Token::Kind rightToken,
150 const std::function<ParseResult()> &parseElement,
151 bool allowEmptyList = true);
152
153 /// Parse a comma separated list of elements that must have at least one entry
154 /// in it.
155 ParseResult
156 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700157
Chris Lattnerf7e22732018-06-22 22:03:48 -0700158 // We have two forms of parsing methods - those that return a non-null
159 // pointer on success, and those that return a ParseResult to indicate whether
160 // they returned a failure. The second class fills in by-reference arguments
161 // as the results of their action.
162
Chris Lattnere79379a2018-06-22 10:39:19 -0700163 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700164 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700165 Type *parseElementType();
166 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700167 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700168 Type *parseTensorType();
169 Type *parseMemRefType();
170 Type *parseFunctionType();
171 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700172 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700173 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700174
Chris Lattner7121b802018-07-04 20:45:39 -0700175 // Attribute parsing.
176 Attribute *parseAttribute();
177 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
178
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700179 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700180 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700181 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700182
Chris Lattner48af7d12018-07-09 19:05:38 -0700183private:
184 // The Parser is subclassed and reinstantiated. Do not add additional
185 // non-trivial state here, add it to the ParserState class.
186 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700187};
188} // end anonymous namespace
189
190//===----------------------------------------------------------------------===//
191// Helper methods.
192//===----------------------------------------------------------------------===//
193
Chris Lattner4c95a502018-06-23 16:03:42 -0700194ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700195 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700196 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700197 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700198 return ParseFailure;
199
Chris Lattner48af7d12018-07-09 19:05:38 -0700200 auto &sourceMgr = state.lex.getSourceMgr();
201 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700202 return ParseFailure;
203}
204
Chris Lattnerf7702a62018-07-23 17:30:01 -0700205/// Consume the specified token if present and return success. On failure,
206/// output a diagnostic and return failure.
207ParseResult Parser::parseToken(Token::Kind expectedToken,
208 const Twine &message) {
209 if (consumeIf(expectedToken))
210 return ParseSuccess;
211 return emitError(message);
212}
213
Chris Lattner40746442018-07-21 14:32:09 -0700214/// Parse a comma separated list of elements that must have at least one entry
215/// in it.
216ParseResult Parser::parseCommaSeparatedList(
217 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700218 // Non-empty case starts with an element.
219 if (parseElement())
220 return ParseFailure;
221
222 // Otherwise we have a list of comma separated elements.
223 while (consumeIf(Token::comma)) {
224 if (parseElement())
225 return ParseFailure;
226 }
Chris Lattner40746442018-07-21 14:32:09 -0700227 return ParseSuccess;
228}
229
230/// Parse a comma-separated list of elements, terminated with an arbitrary
231/// token. This allows empty lists if allowEmptyList is true.
232///
233/// abstract-list ::= rightToken // if allowEmptyList == true
234/// abstract-list ::= element (',' element)* rightToken
235///
236ParseResult Parser::parseCommaSeparatedListUntil(
237 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
238 bool allowEmptyList) {
239 // Handle the empty case.
240 if (getToken().is(rightToken)) {
241 if (!allowEmptyList)
242 return emitError("expected list element");
243 consumeToken(rightToken);
244 return ParseSuccess;
245 }
246
Chris Lattnerf7702a62018-07-23 17:30:01 -0700247 if (parseCommaSeparatedList(parseElement) ||
248 parseToken(rightToken, "expected ',' or '" +
249 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700250 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700251
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700252 return ParseSuccess;
253}
Chris Lattnere79379a2018-06-22 10:39:19 -0700254
255//===----------------------------------------------------------------------===//
256// Type Parsing
257//===----------------------------------------------------------------------===//
258
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700259/// Parse the low-level fixed dtypes in the system.
260///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700261/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
262/// primitive-type ::= integer-type
263/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700264///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700265Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700266 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700267 default:
268 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269 case Token::kw_bf16:
270 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700271 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700272 case Token::kw_f16:
273 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700274 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700275 case Token::kw_f32:
276 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700277 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700278 case Token::kw_f64:
279 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700280 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700281 case Token::kw_affineint:
282 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700283 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700284 case Token::kw_tf_control:
285 consumeToken(Token::kw_tf_control);
286 return builder.getTFControlType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700287 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700288 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700289 if (!width.hasValue())
290 return (emitError("invalid integer width"), nullptr);
291 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700292 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700293 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700294 }
295}
296
297/// Parse the element type of a tensor or memref type.
298///
299/// element-type ::= primitive-type | vector-type
300///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700301Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700302 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700303 return parseVectorType();
304
305 return parsePrimitiveType();
306}
307
308/// Parse a vector type.
309///
310/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
311/// const-dimension-list ::= (integer-literal `x`)+
312///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700313VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700314 consumeToken(Token::kw_vector);
315
Chris Lattnerf7702a62018-07-23 17:30:01 -0700316 if (parseToken(Token::less, "expected '<' in vector type"))
317 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700318
Chris Lattner48af7d12018-07-09 19:05:38 -0700319 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700320 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321
322 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700323 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700325 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700326 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700327 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700328 dimensions.push_back(dimension.getValue());
329
330 consumeToken(Token::integer);
331
332 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700333 if (getToken().isNot(Token::bare_identifier) ||
334 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700335 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336
337 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700338 if (getTokenSpelling().size() != 1)
339 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700340
341 // Consume the 'x'.
342 consumeToken(Token::bare_identifier);
343 }
344
345 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700346 auto *elementType = parsePrimitiveType();
347 if (!elementType)
348 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700349
Chris Lattnerf7702a62018-07-23 17:30:01 -0700350 if (parseToken(Token::greater, "expected '>' in vector type"))
351 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700352
Chris Lattnerf7e22732018-06-22 22:03:48 -0700353 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700354}
355
356/// Parse a dimension list of a tensor or memref type. This populates the
357/// dimension list, returning -1 for the '?' dimensions.
358///
359/// dimension-list-ranked ::= (dimension `x`)*
360/// dimension ::= `?` | integer-literal
361///
362ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700363 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700364 if (consumeIf(Token::question)) {
365 dimensions.push_back(-1);
366 } else {
367 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700368 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700369 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
370 return emitError("invalid dimension");
371 dimensions.push_back((int)dimension.getValue());
372 consumeToken(Token::integer);
373 }
374
375 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700376 if (getToken().isNot(Token::bare_identifier) ||
377 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700378 return emitError("expected 'x' in dimension list");
379
380 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700381 if (getTokenSpelling().size() != 1)
382 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700383
384 // Consume the 'x'.
385 consumeToken(Token::bare_identifier);
386 }
387
388 return ParseSuccess;
389}
390
391/// Parse a tensor type.
392///
393/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
394/// dimension-list ::= dimension-list-ranked | `??`
395///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700396Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700397 consumeToken(Token::kw_tensor);
398
Chris Lattnerf7702a62018-07-23 17:30:01 -0700399 if (parseToken(Token::less, "expected '<' in tensor type"))
400 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700401
402 bool isUnranked;
403 SmallVector<int, 4> dimensions;
404
405 if (consumeIf(Token::questionquestion)) {
406 isUnranked = true;
407 } else {
408 isUnranked = false;
409 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700410 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700411 }
412
413 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700414 auto elementType = parseElementType();
415 if (!elementType)
416 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700417
Chris Lattnerf7702a62018-07-23 17:30:01 -0700418 if (parseToken(Token::greater, "expected '>' in tensor type"))
419 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700420
MLIR Team355ec862018-06-23 18:09:09 -0700421 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700422 return builder.getTensorType(elementType);
423 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700424}
425
426/// Parse a memref type.
427///
428/// memref-type ::= `memref` `<` dimension-list-ranked element-type
429/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
430///
431/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
432/// memory-space ::= integer-literal /* | TODO: address-space-id */
433///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700434Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700435 consumeToken(Token::kw_memref);
436
Chris Lattnerf7702a62018-07-23 17:30:01 -0700437 if (parseToken(Token::less, "expected '<' in memref type"))
438 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700439
440 SmallVector<int, 4> dimensions;
441 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700442 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700443
444 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700445 auto elementType = parseElementType();
446 if (!elementType)
447 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700448
MLIR Team718c82f2018-07-16 09:45:22 -0700449 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700450 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700451 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700452 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700453
MLIR Team718c82f2018-07-16 09:45:22 -0700454 auto parseElt = [&]() -> ParseResult {
455 if (getToken().is(Token::integer)) {
456 // Parse memory space.
457 if (parsedMemorySpace)
458 return emitError("multiple memory spaces specified in memref type");
459 auto v = getToken().getUnsignedIntegerValue();
460 if (!v.hasValue())
461 return emitError("invalid memory space in memref type");
462 memorySpace = v.getValue();
463 consumeToken(Token::integer);
464 parsedMemorySpace = true;
465 } else {
466 // Parse affine map.
467 if (parsedMemorySpace)
468 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700469 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700470 if (affineMap == nullptr)
471 return ParseFailure;
472 affineMapComposition.push_back(affineMap);
473 }
474 return ParseSuccess;
475 };
476
Chris Lattner413db6a2018-07-25 12:55:50 -0700477 // Parse a list of mappings and address space if present.
478 if (consumeIf(Token::comma)) {
479 // Parse comma separated list of affine maps, followed by memory space.
480 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
481 /*allowEmptyList=*/false)) {
482 return nullptr;
483 }
484 } else {
485 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
486 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700487 }
MLIR Team718c82f2018-07-16 09:45:22 -0700488
489 return MemRefType::get(dimensions, elementType, affineMapComposition,
490 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700491}
492
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700493/// Parse a function type.
494///
495/// function-type ::= type-list-parens `->` type-list
496///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700497Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700498 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700499
Chris Lattnerf7702a62018-07-23 17:30:01 -0700500 SmallVector<Type *, 4> arguments, results;
501 if (parseTypeList(arguments) ||
502 parseToken(Token::arrow, "expected '->' in function type") ||
503 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700504 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700505
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700506 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700507}
508
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700509/// Parse an arbitrary type.
510///
511/// type ::= primitive-type
512/// | vector-type
513/// | tensor-type
514/// | memref-type
515/// | function-type
516/// element-type ::= primitive-type | vector-type
517///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700518Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700519 switch (getToken().getKind()) {
James Molloy0ff71542018-07-23 16:56:32 -0700520 case Token::kw_memref:
521 return parseMemRefType();
522 case Token::kw_tensor:
523 return parseTensorType();
524 case Token::kw_vector:
525 return parseVectorType();
526 case Token::l_paren:
527 return parseFunctionType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700528 default:
529 return parsePrimitiveType();
530 }
531}
532
Chris Lattner1604e472018-07-23 08:42:19 -0700533/// Parse a list of types without an enclosing parenthesis. The list must have
534/// at least one member.
535///
536/// type-list-no-parens ::= type (`,` type)*
537///
538ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
539 auto parseElt = [&]() -> ParseResult {
540 auto elt = parseType();
541 elements.push_back(elt);
542 return elt ? ParseSuccess : ParseFailure;
543 };
544
545 return parseCommaSeparatedList(parseElt);
546}
547
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700548/// Parse a "type list", which is a singular type, or a parenthesized list of
549/// types.
550///
551/// type-list ::= type-list-parens | type
552/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700553/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700554///
James Molloy0ff71542018-07-23 16:56:32 -0700555ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700556 auto parseElt = [&]() -> ParseResult {
557 auto elt = parseType();
558 elements.push_back(elt);
559 return elt ? ParseSuccess : ParseFailure;
560 };
561
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562 // If there is no parens, then it must be a singular type.
563 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700564 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700565
Chris Lattner40746442018-07-21 14:32:09 -0700566 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700567 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700568
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700569 return ParseSuccess;
570}
571
Chris Lattner4c95a502018-06-23 16:03:42 -0700572//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700573// Attribute parsing.
574//===----------------------------------------------------------------------===//
575
Chris Lattner7121b802018-07-04 20:45:39 -0700576/// Attribute parsing.
577///
578/// attribute-value ::= bool-literal
579/// | integer-literal
580/// | float-literal
581/// | string-literal
582/// | `[` (attribute-value (`,` attribute-value)*)? `]`
583///
584Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700585 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700586 case Token::kw_true:
587 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700588 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700589 case Token::kw_false:
590 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700591 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700592
593 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700594 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700595 if (!val.hasValue() || (int64_t)val.getValue() < 0)
596 return (emitError("integer too large for attribute"), nullptr);
597 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700598 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700599 }
600
601 case Token::minus: {
602 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700603 if (getToken().is(Token::integer)) {
604 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700605 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
606 return (emitError("integer too large for attribute"), nullptr);
607 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700608 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700609 }
610
611 return (emitError("expected constant integer or floating point value"),
612 nullptr);
613 }
614
615 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700616 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700617 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700618 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700619 }
620
Chris Lattner85ee1512018-07-25 11:15:20 -0700621 case Token::l_square: {
622 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700623 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700624
625 auto parseElt = [&]() -> ParseResult {
626 elements.push_back(parseAttribute());
627 return elements.back() ? ParseSuccess : ParseFailure;
628 };
629
Chris Lattner85ee1512018-07-25 11:15:20 -0700630 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700631 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700632 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700633 }
634 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700635 // Try to parse affine map reference.
James Molloy0ff71542018-07-23 16:56:32 -0700636 auto *affineMap = parseAffineMapReference();
MLIR Teamb61885d2018-07-18 16:29:21 -0700637 if (affineMap != nullptr)
638 return builder.getAffineMapAttr(affineMap);
639
Chris Lattner7121b802018-07-04 20:45:39 -0700640 // TODO: Handle floating point.
641 return (emitError("expected constant attribute value"), nullptr);
642 }
643}
644
Chris Lattner7121b802018-07-04 20:45:39 -0700645/// Attribute dictionary.
646///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700647/// attribute-dict ::= `{` `}`
648/// | `{` attribute-entry (`,` attribute-entry)* `}`
649/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700650///
James Molloy0ff71542018-07-23 16:56:32 -0700651ParseResult
652Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700653 consumeToken(Token::l_brace);
654
655 auto parseElt = [&]() -> ParseResult {
656 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700657 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
658 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700659 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700660 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700661 consumeToken();
662
Chris Lattnerf7702a62018-07-23 17:30:01 -0700663 if (parseToken(Token::colon, "expected ':' in attribute list"))
664 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700665
666 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700667 if (!attr)
668 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700669
670 attributes.push_back({nameId, attr});
671 return ParseSuccess;
672 };
673
Chris Lattner40746442018-07-21 14:32:09 -0700674 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700675 return ParseFailure;
676
677 return ParseSuccess;
678}
679
680//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700681// Polyhedral structures.
682//===----------------------------------------------------------------------===//
683
Chris Lattner2e595eb2018-07-10 10:08:27 -0700684/// Lower precedence ops (all at the same precedence level). LNoOp is false in
685/// the boolean sense.
686enum AffineLowPrecOp {
687 /// Null value.
688 LNoOp,
689 Add,
690 Sub
691};
MLIR Teamf85a6262018-06-27 11:03:08 -0700692
Chris Lattner2e595eb2018-07-10 10:08:27 -0700693/// Higher precedence ops - all at the same precedence level. HNoOp is false in
694/// the boolean sense.
695enum AffineHighPrecOp {
696 /// Null value.
697 HNoOp,
698 Mul,
699 FloorDiv,
700 CeilDiv,
701 Mod
702};
Chris Lattner7121b802018-07-04 20:45:39 -0700703
Chris Lattner2e595eb2018-07-10 10:08:27 -0700704namespace {
705/// This is a specialized parser for AffineMap's, maintaining the state
706/// transient to their bodies.
707class AffineMapParser : public Parser {
708public:
709 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700710
Chris Lattner2e595eb2018-07-10 10:08:27 -0700711 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700712
Chris Lattner2e595eb2018-07-10 10:08:27 -0700713private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700714 // Binary affine op parsing.
715 AffineLowPrecOp consumeIfLowPrecOp();
716 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700717
Chris Lattner2e595eb2018-07-10 10:08:27 -0700718 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700719 ParseResult parseDimIdList(unsigned &numDims);
720 ParseResult parseSymbolIdList(unsigned &numSymbols);
721 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700722
723 AffineExpr *parseAffineExpr();
724 AffineExpr *parseParentheticalExpr();
725 AffineExpr *parseNegateExpression(AffineExpr *lhs);
726 AffineExpr *parseIntegerExpr();
727 AffineExpr *parseBareIdExpr();
728
729 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700730 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700731 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
732 AffineExpr *rhs);
733 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
734 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
735 AffineLowPrecOp llhsOp);
736 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700737 AffineHighPrecOp llhsOp,
738 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700739
740private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700741 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700742};
743} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700744
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700745/// Create an affine binary high precedence op expression (mul's, div's, mod).
746/// opLoc is the location of the op token to be used to report errors
747/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700748AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
749 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700750 AffineExpr *rhs,
751 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700752 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700753 switch (op) {
754 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700755 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700756 emitError(opLoc, "non-affine expression: at least one of the multiply "
757 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700758 return nullptr;
759 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700760 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700761 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700762 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700763 emitError(opLoc, "non-affine expression: right operand of floordiv "
764 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700765 return nullptr;
766 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700767 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700768 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700769 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700770 emitError(opLoc, "non-affine expression: right operand of ceildiv "
771 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700772 return nullptr;
773 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700774 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700775 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700776 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700777 emitError(opLoc, "non-affine expression: right operand of mod "
778 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700779 return nullptr;
780 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700781 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700782 case HNoOp:
783 llvm_unreachable("can't create affine expression for null high prec op");
784 return nullptr;
785 }
786}
787
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700788/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700789AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
790 AffineExpr *lhs,
791 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700792 switch (op) {
793 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700794 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700795 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700796 return builder.getAddExpr(
797 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700798 case AffineLowPrecOp::LNoOp:
799 llvm_unreachable("can't create affine expression for null low prec op");
800 return nullptr;
801 }
802}
803
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700804/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700805/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700806AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700807 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700808 case Token::plus:
809 consumeToken(Token::plus);
810 return AffineLowPrecOp::Add;
811 case Token::minus:
812 consumeToken(Token::minus);
813 return AffineLowPrecOp::Sub;
814 default:
815 return AffineLowPrecOp::LNoOp;
816 }
817}
818
819/// Consume this token if it is a higher precedence affine op (there are only
820/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700822 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700823 case Token::star:
824 consumeToken(Token::star);
825 return Mul;
826 case Token::kw_floordiv:
827 consumeToken(Token::kw_floordiv);
828 return FloorDiv;
829 case Token::kw_ceildiv:
830 consumeToken(Token::kw_ceildiv);
831 return CeilDiv;
832 case Token::kw_mod:
833 consumeToken(Token::kw_mod);
834 return Mod;
835 default:
836 return HNoOp;
837 }
838}
839
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700840/// Parse a high precedence op expression list: mul, div, and mod are high
841/// precedence binary ops, i.e., parse a
842/// expr_1 op_1 expr_2 op_2 ... expr_n
843/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
844/// All affine binary ops are left associative.
845/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
846/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700847/// null. llhsOpLoc is the location of the llhsOp token that will be used to
848/// report an error for non-conforming expressions.
849AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
850 AffineHighPrecOp llhsOp,
851 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700852 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853 if (!lhs)
854 return nullptr;
855
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700857 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700858 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700859 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700860 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700861 if (!expr)
862 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700864 }
865 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700866 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700867 }
868
869 // This is the last operand in this expression.
870 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700871 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700872
873 // No llhs, 'lhs' itself is the expression.
874 return lhs;
875}
876
877/// Parse an affine expression inside parentheses.
878///
879/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700880AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700881 if (parseToken(Token::l_paren, "expected '('"))
882 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700883 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700885
Chris Lattner2e595eb2018-07-10 10:08:27 -0700886 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700887 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700888 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700889 if (parseToken(Token::r_paren, "expected ')'"))
890 return nullptr;
891
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700892 return expr;
893}
894
895/// Parse the negation expression.
896///
897/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700898AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700899 if (parseToken(Token::minus, "expected '-'"))
900 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700901
Chris Lattner2e595eb2018-07-10 10:08:27 -0700902 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700903 // Since negation has the highest precedence of all ops (including high
904 // precedence ops) but lower than parentheses, we are only going to use
905 // parseAffineOperandExpr instead of parseAffineExpr here.
906 if (!operand)
907 // Extra error message although parseAffineOperandExpr would have
908 // complained. Leads to a better diagnostic.
909 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700910 auto *minusOne = builder.getConstantExpr(-1);
911 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700912}
913
914/// Parse a bare id that may appear in an affine expression.
915///
916/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700917AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700918 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700919 return (emitError("expected bare identifier"), nullptr);
920
Chris Lattner48af7d12018-07-09 19:05:38 -0700921 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700922 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700923 if (entry.first == sRef) {
924 consumeToken(Token::bare_identifier);
925 return entry.second;
926 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700928
929 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700930}
931
932/// Parse a positive integral constant appearing in an affine expression.
933///
934/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700935AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700936 // No need to handle negative numbers separately here. They are naturally
937 // handled via the unary negation operator, although (FIXME) MININT_64 still
938 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700939 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940 return (emitError("expected integer"), nullptr);
941
Chris Lattner48af7d12018-07-09 19:05:38 -0700942 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
944 return (emitError("constant too large for affineint"), nullptr);
945 }
946 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700947 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700948}
949
950/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700951/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
952/// operator, the rhs of which is being parsed. This is used to determine
953/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700954// Eg: for an expression without parentheses (like i + j + k + l), each
955// of the four identifiers is an operand. For i + j*k + l, j*k is not an
956// operand expression, it's an op expression and will be parsed via
957// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
958// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700959AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700960 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700962 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700963 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700964 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700965 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700966 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700967 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700968 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700969 case Token::kw_ceildiv:
970 case Token::kw_floordiv:
971 case Token::kw_mod:
972 case Token::plus:
973 case Token::star:
974 if (lhs)
975 emitError("missing right operand of binary operator");
976 else
977 emitError("missing left operand of binary operator");
978 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700979 default:
980 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700981 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700982 else
983 emitError("expected affine expression");
984 return nullptr;
985 }
986}
987
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700988/// Parse affine expressions that are bare-id's, integer constants,
989/// parenthetical affine expressions, and affine op expressions that are a
990/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700991///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700992/// All binary op's associate from left to right.
993///
994/// {add, sub} have lower precedence than {mul, div, and mod}.
995///
Uday Bondhugula76345202018-07-09 13:47:52 -0700996/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
997/// ceildiv, and mod are at the same higher precedence level. Negation has
998/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700999///
1000/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001001/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1002/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1003/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001004/// associativity.
1005///
1006/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001007/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1008/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001009AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1010 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001011 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001012 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001013 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001014
1015 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001016 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001017 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001018 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001019 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001020 }
1021 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001022 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001023 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001024 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001025 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001026 // We have a higher precedence op here. Get the rhs operand for the llhs
1027 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001028 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001029 if (!highRes)
1030 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001031
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001033 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001034 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001035 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001036
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001037 // Recurse for subsequent low prec op's after the affine high prec op
1038 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001039 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1040 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001041 return expr;
1042 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001043 // Last operand in the expression list.
1044 if (llhs)
1045 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1046 // No llhs, 'lhs' itself is the expression.
1047 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001048}
1049
1050/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001051/// affine-expr ::= `(` affine-expr `)`
1052/// | `-` affine-expr
1053/// | affine-expr `+` affine-expr
1054/// | affine-expr `-` affine-expr
1055/// | affine-expr `*` affine-expr
1056/// | affine-expr `floordiv` affine-expr
1057/// | affine-expr `ceildiv` affine-expr
1058/// | affine-expr `mod` affine-expr
1059/// | bare-id
1060/// | integer-literal
1061///
1062/// Additional conditions are checked depending on the production. For eg., one
1063/// of the operands for `*` has to be either constant/symbolic; the second
1064/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001065AffineExpr *AffineMapParser::parseAffineExpr() {
1066 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001067}
1068
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001069/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001070/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001071/// identifier.
1072ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001073 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001074 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001075
1076 auto name = getTokenSpelling();
1077 for (auto entry : dimsAndSymbols) {
1078 if (entry.first == name)
1079 return emitError("redefinition of identifier '" + Twine(name) + "'");
1080 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001081 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001082
1083 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001085}
1086
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001087/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001088ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1089 consumeToken(Token::l_square);
1090 auto parseElt = [&]() -> ParseResult {
1091 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1092 return parseIdentifierDefinition(symbol);
1093 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001094 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001095}
1096
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001097/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001098ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001099 if (parseToken(Token::l_paren,
1100 "expected '(' at start of dimensional identifiers list"))
1101 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001102
Chris Lattner413db6a2018-07-25 12:55:50 -07001103 auto parseElt = [&]() -> ParseResult {
1104 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1105 return parseIdentifierDefinition(dimension);
1106 };
Chris Lattner40746442018-07-21 14:32:09 -07001107 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001108}
1109
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001110/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001111///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001112/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1113/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1114/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001115///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001116/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001117AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001118 unsigned numDims = 0, numSymbols = 0;
1119
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001120 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001121 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001122 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001123
1124 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001125 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001126 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001127 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001128 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001129
1130 if (parseToken(Token::arrow, "expected '->' or '['") ||
1131 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001132 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001133
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001134 SmallVector<AffineExpr *, 4> exprs;
1135 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001136 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001137 ParseResult res = elt ? ParseSuccess : ParseFailure;
1138 exprs.push_back(elt);
1139 return res;
1140 };
1141
1142 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001143 // affine expressions); the list cannot be empty.
1144 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001145 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001146 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001147
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001148 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001149 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1150 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1151 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001152 // TODO: check if sizes are non-negative whenever they are constant.
1153 SmallVector<AffineExpr *, 4> rangeSizes;
1154 if (consumeIf(Token::kw_size)) {
1155 // Location of the l_paren token (if it exists) for error reporting later.
1156 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001157 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1158 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001159
1160 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001161 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001162 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001163 if (!elt)
1164 return ParseFailure;
1165
1166 if (!elt->isSymbolicOrConstant())
1167 return emitError(loc,
1168 "size expressions cannot refer to dimension values");
1169
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001170 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001171 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001172 };
1173
Chris Lattner40746442018-07-21 14:32:09 -07001174 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001175 return nullptr;
1176 if (exprs.size() > rangeSizes.size())
1177 return (emitError(loc, "fewer range sizes than range expressions"),
1178 nullptr);
1179 if (exprs.size() < rangeSizes.size())
1180 return (emitError(loc, "more range sizes than range expressions"),
1181 nullptr);
1182 }
1183
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001184 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001185 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001186}
1187
Chris Lattner2e595eb2018-07-10 10:08:27 -07001188AffineMap *Parser::parseAffineMapInline() {
1189 return AffineMapParser(state).parseAffineMapInline();
1190}
1191
MLIR Team718c82f2018-07-16 09:45:22 -07001192AffineMap *Parser::parseAffineMapReference() {
1193 if (getToken().is(Token::hash_identifier)) {
1194 // Parse affine map identifier and verify that it exists.
1195 StringRef affineMapId = getTokenSpelling().drop_front();
1196 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1197 return (emitError("undefined affine map id '" + affineMapId + "'"),
1198 nullptr);
1199 consumeToken(Token::hash_identifier);
1200 return getState().affineMapDefinitions[affineMapId];
1201 }
1202 // Try to parse inline affine map.
1203 return parseAffineMapInline();
1204}
1205
MLIR Teamf85a6262018-06-27 11:03:08 -07001206//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001207// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001208//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001209
Chris Lattner7f9cc272018-07-19 08:35:28 -07001210namespace {
1211/// This class contains parser state that is common across CFG and ML functions,
1212/// notably for dealing with operations and SSA values.
1213class FunctionParser : public Parser {
1214public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001215 enum class Kind { CFGFunc, MLFunc };
1216
1217 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001218
Chris Lattner6119d382018-07-20 18:41:34 -07001219 /// After the function is finished parsing, this function checks to see if
1220 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001221 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001222
1223 /// This represents a use of an SSA value in the program. The first two
1224 /// entries in the tuple are the name and result number of a reference. The
1225 /// third is the location of the reference, which is used in case this ends up
1226 /// being a use of an undefined value.
1227 struct SSAUseInfo {
1228 StringRef name; // Value name, e.g. %42 or %abc
1229 unsigned number; // Number, specified with #12
1230 SMLoc loc; // Location of first definition or use.
1231 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001232
1233 /// Given a reference to an SSA value and its type, return a reference. This
1234 /// returns null on failure.
1235 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1236
1237 /// Register a definition of a value with the symbol table.
1238 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1239
1240 // SSA parsing productions.
1241 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001242 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001243
1244 template <typename ResultType>
1245 ResultType parseSSADefOrUseAndType(
1246 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1247
1248 SSAValue *parseSSAUseAndType() {
1249 return parseSSADefOrUseAndType<SSAValue *>(
1250 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1251 return resolveSSAUse(useInfo, type);
1252 });
1253 }
Chris Lattner40746442018-07-21 14:32:09 -07001254
1255 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001256 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001257 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1258 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001259
1260 // Operations
1261 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001262 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1263 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001264
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001265protected:
1266 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1267
Chris Lattner7f9cc272018-07-19 08:35:28 -07001268private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001269 /// Kind indicates if this is CFG or ML function parser.
1270 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001271 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001272 /// their name. This has one entry per result number.
1273 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1274
1275 /// These are all of the placeholders we've made along with the location of
1276 /// their first reference, to allow checking for use of undefined values.
1277 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1278
1279 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1280
1281 /// Return true if this is a forward reference.
1282 bool isForwardReferencePlaceholder(SSAValue *value) {
1283 return forwardReferencePlaceholders.count(value);
1284 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001285};
1286} // end anonymous namespace
1287
Chris Lattner6119d382018-07-20 18:41:34 -07001288/// Create and remember a new placeholder for a forward reference.
1289SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1290 Type *type) {
1291 // Forward references are always created as instructions, even in ML
1292 // functions, because we just need something with a def/use chain.
1293 //
1294 // We create these placeholders as having an empty name, which we know cannot
1295 // be created through normal user input, allowing us to distinguish them.
1296 auto name = Identifier::get("placeholder", getContext());
1297 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1298 getContext());
1299 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1300 return inst->getResult(0);
1301}
1302
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001303/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001304/// it specifies. This returns null on failure.
1305SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001306 auto &entries = values[useInfo.name];
1307
Chris Lattner7f9cc272018-07-19 08:35:28 -07001308 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001309 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1310 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001311 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001312 if (result->getType() == type)
1313 return result;
1314
Chris Lattner6119d382018-07-20 18:41:34 -07001315 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1316 "' expects different type than prior uses");
1317 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001318 return nullptr;
1319 }
1320
Chris Lattner6119d382018-07-20 18:41:34 -07001321 // Make sure we have enough slots for this.
1322 if (entries.size() <= useInfo.number)
1323 entries.resize(useInfo.number + 1);
1324
1325 // If the value has already been defined and this is an overly large result
1326 // number, diagnose that.
1327 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1328 return (emitError(useInfo.loc, "reference to invalid result number"),
1329 nullptr);
1330
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001331 if (getKind() == Kind::MLFunc)
1332 return (
1333 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1334 nullptr);
1335
1336 // Otherwise, this is a forward reference. If we are in ML function return
1337 // an error. In CFG function, create a placeholder and remember
Chris Lattner6119d382018-07-20 18:41:34 -07001338 // that we did so.
1339 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1340 entries[useInfo.number].first = result;
1341 entries[useInfo.number].second = useInfo.loc;
1342 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001343}
1344
1345/// Register a definition of a value with the symbol table.
1346ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001347 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001348
Chris Lattner6119d382018-07-20 18:41:34 -07001349 // Make sure there is a slot for this value.
1350 if (entries.size() <= useInfo.number)
1351 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001352
Chris Lattner6119d382018-07-20 18:41:34 -07001353 // If we already have an entry for this, check to see if it was a definition
1354 // or a forward reference.
1355 if (auto *existing = entries[useInfo.number].first) {
1356 if (!isForwardReferencePlaceholder(existing)) {
1357 emitError(useInfo.loc,
1358 "redefinition of SSA value '" + useInfo.name + "'");
1359 return emitError(entries[useInfo.number].second,
1360 "previously defined here");
1361 }
1362
1363 // If it was a forward reference, update everything that used it to use the
1364 // actual definition instead, delete the forward ref, and remove it from our
1365 // set of forward references we track.
1366 existing->replaceAllUsesWith(value);
1367 existing->getDefiningInst()->destroy();
1368 forwardReferencePlaceholders.erase(existing);
1369 }
1370
1371 entries[useInfo.number].first = value;
1372 entries[useInfo.number].second = useInfo.loc;
1373 return ParseSuccess;
1374}
1375
1376/// After the function is finished parsing, this function checks to see if
1377/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001378ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001379 // Check for any forward references that are left. If we find any, error out.
1380 if (!forwardReferencePlaceholders.empty()) {
1381 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1382 // Iteration over the map isn't determinstic, so sort by source location.
1383 for (auto entry : forwardReferencePlaceholders)
1384 errors.push_back({entry.second.getPointer(), entry.first});
1385 llvm::array_pod_sort(errors.begin(), errors.end());
1386
1387 for (auto entry : errors)
1388 emitError(SMLoc::getFromPointer(entry.first),
1389 "use of undeclared SSA value name");
1390 return ParseFailure;
1391 }
1392
Chris Lattner40746442018-07-21 14:32:09 -07001393 // Run the verifier on this function. If an error is detected, report it.
1394 std::string errorString;
1395 if (func->verify(&errorString))
1396 return emitError(loc, errorString);
1397
Chris Lattner6119d382018-07-20 18:41:34 -07001398 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001399}
1400
Chris Lattner78276e32018-07-07 15:48:26 -07001401/// Parse a SSA operand for an instruction or statement.
1402///
James Molloy61a656c2018-07-22 15:45:24 -07001403/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001404///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001405ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001406 result.name = getTokenSpelling();
1407 result.number = 0;
1408 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001409 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1410 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001411
1412 // If we have an affine map ID, it is a result number.
1413 if (getToken().is(Token::hash_identifier)) {
1414 if (auto value = getToken().getHashIdentifierNumber())
1415 result.number = value.getValue();
1416 else
1417 return emitError("invalid SSA value result number");
1418 consumeToken(Token::hash_identifier);
1419 }
1420
Chris Lattner7f9cc272018-07-19 08:35:28 -07001421 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001422}
1423
1424/// Parse a (possibly empty) list of SSA operands.
1425///
1426/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1427/// ssa-use-list-opt ::= ssa-use-list?
1428///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001429ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001430FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001431 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001432 return ParseSuccess;
1433 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001434 SSAUseInfo result;
1435 if (parseSSAUse(result))
1436 return ParseFailure;
1437 results.push_back(result);
1438 return ParseSuccess;
1439 });
Chris Lattner78276e32018-07-07 15:48:26 -07001440}
1441
1442/// Parse an SSA use with an associated type.
1443///
1444/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001445template <typename ResultType>
1446ResultType FunctionParser::parseSSADefOrUseAndType(
1447 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001448
Chris Lattnerf7702a62018-07-23 17:30:01 -07001449 SSAUseInfo useInfo;
1450 if (parseSSAUse(useInfo) ||
1451 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1452 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001453
Chris Lattner7f9cc272018-07-19 08:35:28 -07001454 auto *type = parseType();
1455 if (!type)
1456 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001457
James Molloy61a656c2018-07-22 15:45:24 -07001458 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001459}
1460
Chris Lattner2c402672018-07-23 11:56:17 -07001461/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1462/// followed by a type list. If hasParens is true, then the operands are
1463/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001464///
Chris Lattner2c402672018-07-23 11:56:17 -07001465/// ssa-use-and-type-list[parens]
1466/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1467///
1468/// ssa-use-and-type-list[!parens]
1469/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001470///
Chris Lattner40746442018-07-21 14:32:09 -07001471template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001472ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001473 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1474
1475 // If we are in the parenthesized form and no paren exists, then we succeed
1476 // with an empty list.
1477 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001478 return ParseSuccess;
1479
Chris Lattner2c402672018-07-23 11:56:17 -07001480 SmallVector<SSAUseInfo, 4> valueIDs;
1481 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001482 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001483
1484 if (isParenthesized && !consumeIf(Token::r_paren))
1485 return emitError("expected ')' in operand list");
1486
1487 // If there were no operands, then there is no colon or type lists.
1488 if (valueIDs.empty())
1489 return ParseSuccess;
1490
Chris Lattner2c402672018-07-23 11:56:17 -07001491 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001492 if (parseToken(Token::colon, "expected ':' in operand list") ||
1493 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001494 return ParseFailure;
1495
1496 if (valueIDs.size() != types.size())
1497 return emitError("expected " + Twine(valueIDs.size()) +
1498 " types to match operand list");
1499
1500 results.reserve(valueIDs.size());
1501 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1502 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1503 results.push_back(cast<ValueTy>(value));
1504 else
1505 return ParseFailure;
1506 }
1507
1508 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001509}
1510
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001511/// Parse the CFG or MLFunc operation.
1512///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001513/// operation ::=
1514/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1515/// `:` function-type
1516///
1517ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001518FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001519 auto loc = getToken().getLoc();
1520
1521 StringRef resultID;
1522 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001523 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001524 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001525 if (parseToken(Token::equal, "expected '=' after SSA name"))
1526 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001527 }
1528
Chris Lattner85ee1512018-07-25 11:15:20 -07001529 Operation *op;
1530 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1531 op = parseCustomOperation(createOpFunc);
1532 else if (getToken().is(Token::string))
1533 op = parseVerboseOperation(createOpFunc);
1534 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001535 return emitError("expected operation name in quotes");
1536
Chris Lattner85ee1512018-07-25 11:15:20 -07001537 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001538 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001539 return ParseFailure;
1540
1541 // We just parsed an operation. If it is a recognized one, verify that it
1542 // is structurally as we expect. If not, produce an error with a reasonable
1543 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001544 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1545 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001546 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001547 }
1548
Chris Lattner7f9cc272018-07-19 08:35:28 -07001549 // If the instruction had a name, register it.
1550 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001551 if (op->getNumResults() == 0)
1552 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001553
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001554 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
1555 addDefinition({resultID, i, loc}, op->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001556 }
1557
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001558 return ParseSuccess;
1559}
Chris Lattnere79379a2018-06-22 10:39:19 -07001560
Chris Lattner85ee1512018-07-25 11:15:20 -07001561Operation *FunctionParser::parseVerboseOperation(
1562 const CreateOperationFunction &createOpFunc) {
1563 auto name = getToken().getStringValue();
1564 if (name.empty())
1565 return (emitError("empty operation name is invalid"), nullptr);
1566
1567 consumeToken(Token::string);
1568
1569 // Parse the operand list.
1570 SmallVector<SSAUseInfo, 8> operandInfos;
1571
1572 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1573 parseOptionalSSAUseList(operandInfos) ||
1574 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1575 return nullptr;
1576 }
1577
1578 SmallVector<NamedAttribute, 4> attributes;
1579 if (getToken().is(Token::l_brace)) {
1580 if (parseAttributeDict(attributes))
1581 return nullptr;
1582 }
1583
1584 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1585 return nullptr;
1586
1587 auto typeLoc = getToken().getLoc();
1588 auto type = parseType();
1589 if (!type)
1590 return nullptr;
1591 auto fnType = dyn_cast<FunctionType>(type);
1592 if (!fnType)
1593 return (emitError(typeLoc, "expected function type"), nullptr);
1594
1595 // Check that we have the right number of types for the operands.
1596 auto operandTypes = fnType->getInputs();
1597 if (operandTypes.size() != operandInfos.size()) {
1598 auto plural = "s"[operandInfos.size() == 1];
1599 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1600 " operand type" + plural + " but had " +
1601 llvm::utostr(operandTypes.size())),
1602 nullptr);
1603 }
1604
1605 // Resolve all of the operands.
1606 SmallVector<SSAValue *, 8> operands;
1607 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1608 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1609 if (!operands.back())
1610 return nullptr;
1611 }
1612
1613 auto nameId = builder.getIdentifier(name);
1614 return createOpFunc(nameId, operands, fnType->getResults(), attributes);
1615}
1616
1617namespace {
1618class CustomOpAsmParser : public OpAsmParser {
1619public:
1620 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1621 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1622
1623 /// This is an internal helper to parser a colon, we don't want to expose
1624 /// this to clients.
1625 bool internalParseColon(llvm::SMLoc *loc) {
1626 if (loc)
1627 *loc = parser.getToken().getLoc();
1628 return parser.parseToken(Token::colon, "expected ':'");
1629 }
1630
1631 //===--------------------------------------------------------------------===//
1632 // High level parsing methods.
1633 //===--------------------------------------------------------------------===//
1634
1635 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1636 if (loc)
1637 *loc = parser.getToken().getLoc();
1638 return parser.parseToken(Token::comma, "expected ','");
1639 }
1640
1641 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1642 return internalParseColon(loc) || !(result = parser.parseType());
1643 }
1644
1645 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1646 llvm::SMLoc *loc = nullptr) override {
1647 if (internalParseColon(loc))
1648 return true;
1649
1650 do {
1651 if (auto *type = parser.parseType())
1652 result.push_back(type);
1653 else
1654 return true;
1655
1656 } while (parser.consumeIf(Token::comma));
1657 return false;
1658 }
1659
1660 bool parseAttribute(Attribute *&result, llvm::SMLoc *loc = nullptr) override {
1661 if (loc)
1662 *loc = parser.getToken().getLoc();
1663 result = parser.parseAttribute();
1664 return result == nullptr;
1665 }
1666
1667 bool parseOperand(OperandType &result) override {
1668 FunctionParser::SSAUseInfo useInfo;
1669 if (parser.parseSSAUse(useInfo))
1670 return true;
1671
1672 result = {useInfo.loc, useInfo.name, useInfo.number};
1673 return false;
1674 }
1675
1676 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1677 int requiredOperandCount = -1,
1678 Delimeter delimeter = Delimeter::NoDelimeter) override {
1679 auto startLoc = parser.getToken().getLoc();
1680
1681 // Handle delimeters.
1682 switch (delimeter) {
1683 case Delimeter::NoDelimeter:
1684 break;
1685 case Delimeter::ParenDelimeter:
1686 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1687 return true;
1688 break;
1689 case Delimeter::SquareDelimeter:
1690 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1691 return true;
1692 break;
1693 }
1694
1695 // Check for zero operands.
1696 if (parser.getToken().is(Token::percent_identifier)) {
1697 do {
1698 OperandType operand;
1699 if (parseOperand(operand))
1700 return true;
1701 result.push_back(operand);
1702 } while (parser.consumeIf(Token::comma));
1703 }
1704
1705 // Handle delimeters.
1706 switch (delimeter) {
1707 case Delimeter::NoDelimeter:
1708 break;
1709 case Delimeter::ParenDelimeter:
1710 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1711 return true;
1712 break;
1713 case Delimeter::SquareDelimeter:
1714 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1715 return true;
1716 break;
1717 }
1718
1719 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1720 emitError(startLoc,
1721 "expected " + Twine(requiredOperandCount) + " operands");
1722 return false;
1723 }
1724
1725 //===--------------------------------------------------------------------===//
1726 // Methods for interacting with the parser
1727 //===--------------------------------------------------------------------===//
1728
1729 Builder &getBuilder() const override { return parser.builder; }
1730
1731 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1732
1733 bool resolveOperand(OperandType operand, Type *type,
1734 SSAValue *&result) override {
1735 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1736 operand.location};
1737 result = parser.resolveSSAUse(operandInfo, type);
1738 return result == nullptr;
1739 }
1740
1741 /// Emit a diagnostic at the specified location.
1742 void emitError(llvm::SMLoc loc, const Twine &message) override {
1743 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1744 emittedError = true;
1745 }
1746
1747 bool didEmitError() const { return emittedError; }
1748
1749private:
1750 SMLoc nameLoc;
1751 StringRef opName;
1752 FunctionParser &parser;
1753 bool emittedError = false;
1754};
1755} // end anonymous namespace.
1756
1757Operation *FunctionParser::parseCustomOperation(
1758 const CreateOperationFunction &createOpFunc) {
1759 auto opLoc = getToken().getLoc();
1760 auto opName = getTokenSpelling();
1761 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1762
1763 auto *opDefinition = getOperationSet().lookup(opName);
1764 if (!opDefinition) {
1765 opAsmParser.emitError(opLoc, "is unknown");
1766 return nullptr;
1767 }
1768
1769 consumeToken();
1770
1771 // Have the op implementation take a crack and parsing this.
1772 auto result = opDefinition->parseAssembly(&opAsmParser);
1773
1774 // If it emitted an error, we failed.
1775 if (opAsmParser.didEmitError())
1776 return nullptr;
1777
1778 // Otherwise, we succeeded. Use the state it parsed as our op information.
1779 auto nameId = builder.getIdentifier(opName);
1780 return createOpFunc(nameId, result.operands, result.types, result.attributes);
1781}
1782
Chris Lattner48af7d12018-07-09 19:05:38 -07001783//===----------------------------------------------------------------------===//
1784// CFG Functions
1785//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001786
Chris Lattner4c95a502018-06-23 16:03:42 -07001787namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001788/// This is a specialized parser for CFGFunction's, maintaining the state
1789/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001790class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001791public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001792 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001793 : FunctionParser(state, Kind::CFGFunc), function(function),
1794 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001795
1796 ParseResult parseFunctionBody();
1797
1798private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001799 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001800 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001801
1802 /// This builder intentionally shadows the builder in the base class, with a
1803 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001804 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001805
Chris Lattner4c95a502018-06-23 16:03:42 -07001806 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001807 /// already exist. The location specified is the point of use, which allows
1808 /// us to diagnose references to blocks that are not defined precisely.
1809 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1810 auto &blockAndLoc = blocksByName[name];
1811 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001812 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001813 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001814 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001815 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001816 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001817
James Molloy61a656c2018-07-22 15:45:24 -07001818 ParseResult
1819 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1820 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001821 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1822 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001823
Chris Lattner48af7d12018-07-09 19:05:38 -07001824 ParseResult parseBasicBlock();
1825 OperationInst *parseCFGOperation();
1826 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001827};
1828} // end anonymous namespace
1829
James Molloy61a656c2018-07-22 15:45:24 -07001830/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001831/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001832///
1833/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1834///
1835ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1836 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1837 if (getToken().is(Token::r_brace))
1838 return ParseSuccess;
1839
1840 return parseCommaSeparatedList([&]() -> ParseResult {
1841 auto type = parseSSADefOrUseAndType<Type *>(
1842 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1843 BBArgument *arg = owner->addArgument(type);
1844 if (addDefinition(useInfo, arg) == ParseFailure)
1845 return nullptr;
1846 return type;
1847 });
1848 return type ? ParseSuccess : ParseFailure;
1849 });
1850}
1851
Chris Lattner48af7d12018-07-09 19:05:38 -07001852ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001853 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001854 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1855 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001856
1857 // Make sure we have at least one block.
1858 if (getToken().is(Token::r_brace))
1859 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001860
1861 // Parse the list of blocks.
1862 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001863 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001864 return ParseFailure;
1865
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001866 // Verify that all referenced blocks were defined. Iteration over a
1867 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001868 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001869 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001870 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001871 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001872 "reference to an undefined basic block '" + elt.first() +
1873 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001874 }
1875
Chris Lattnera8e47672018-07-25 14:08:16 -07001876 getModule()->getFunctions().push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001877
Chris Lattner40746442018-07-21 14:32:09 -07001878 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001879}
1880
1881/// Basic block declaration.
1882///
1883/// basic-block ::= bb-label instruction* terminator-stmt
1884/// bb-label ::= bb-id bb-arg-list? `:`
1885/// bb-id ::= bare-id
1886/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1887///
Chris Lattner48af7d12018-07-09 19:05:38 -07001888ParseResult CFGFunctionParser::parseBasicBlock() {
1889 SMLoc nameLoc = getToken().getLoc();
1890 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001891 if (parseToken(Token::bare_identifier, "expected basic block name"))
1892 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001893
Chris Lattner48af7d12018-07-09 19:05:38 -07001894 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001895
1896 // If this block has already been parsed, then this is a redefinition with the
1897 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001898 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001899 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1900
Chris Lattner78276e32018-07-07 15:48:26 -07001901 // If an argument list is present, parse it.
1902 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001903 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001904 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1905 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001906 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001907 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001908
James Molloy61a656c2018-07-22 15:45:24 -07001909 // Add the block to the function.
1910 function->push_back(block);
1911
Chris Lattnerf7702a62018-07-23 17:30:01 -07001912 if (parseToken(Token::colon, "expected ':' after basic block name"))
1913 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001914
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001915 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001916 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001917
Chris Lattner7f9cc272018-07-19 08:35:28 -07001918 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1919 ArrayRef<Type *> resultTypes,
1920 ArrayRef<NamedAttribute> attrs) -> Operation * {
1921 SmallVector<CFGValue *, 8> cfgOperands;
1922 cfgOperands.reserve(operands.size());
1923 for (auto *op : operands)
1924 cfgOperands.push_back(cast<CFGValue>(op));
1925 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001926 };
1927
Chris Lattnered65a732018-06-28 20:45:33 -07001928 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001929 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001930 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001931 return ParseFailure;
1932 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001933
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001934 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001935 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001936
1937 return ParseSuccess;
1938}
1939
James Molloy4f788372018-07-24 15:01:27 -07001940ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
1941 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
1942 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1943 if (parseToken(Token::bare_identifier, "expected basic block name"))
1944 return ParseFailure;
1945
1946 if (!consumeIf(Token::l_paren))
1947 return ParseSuccess;
1948 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
1949 parseToken(Token::r_paren, "expected ')' to close argument list"))
1950 return ParseFailure;
1951 return ParseSuccess;
1952}
1953
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001954/// Parse the terminator instruction for a basic block.
1955///
1956/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07001957/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001958/// terminator-stmt ::=
1959/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1960/// terminator-stmt ::= `return` ssa-use-and-type-list?
1961///
Chris Lattner48af7d12018-07-09 19:05:38 -07001962TerminatorInst *CFGFunctionParser::parseTerminator() {
1963 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001964 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001965 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001966
Chris Lattner40746442018-07-21 14:32:09 -07001967 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001968 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07001969
Chris Lattner2c402672018-07-23 11:56:17 -07001970 // Parse any operands.
1971 SmallVector<CFGValue *, 8> operands;
1972 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
1973 return nullptr;
1974 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07001975 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001976
1977 case Token::kw_br: {
1978 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07001979 BasicBlock *destBB;
1980 SmallVector<CFGValue *, 4> values;
1981 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07001982 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07001983 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07001984 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07001985 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001986 }
James Molloy4f788372018-07-24 15:01:27 -07001987
1988 case Token::kw_cond_br: {
1989 consumeToken(Token::kw_cond_br);
1990 SSAUseInfo ssaUse;
1991 if (parseSSAUse(ssaUse))
1992 return nullptr;
1993 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
1994 if (!cond)
1995 return (emitError("expected type was boolean (i1)"), nullptr);
1996 if (parseToken(Token::comma, "expected ',' in conditional branch"))
1997 return nullptr;
1998
1999 BasicBlock *trueBlock;
2000 SmallVector<CFGValue *, 4> trueOperands;
2001 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2002 return nullptr;
2003
2004 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2005 return nullptr;
2006
2007 BasicBlock *falseBlock;
2008 SmallVector<CFGValue *, 4> falseOperands;
2009 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2010 return nullptr;
2011
2012 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2013 falseBlock);
2014 branch->addTrueOperands(trueOperands);
2015 branch->addFalseOperands(falseOperands);
2016 return branch;
2017 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002018 }
2019}
2020
Chris Lattner48af7d12018-07-09 19:05:38 -07002021//===----------------------------------------------------------------------===//
2022// ML Functions
2023//===----------------------------------------------------------------------===//
2024
2025namespace {
2026/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002027class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002028public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002029 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002030 : FunctionParser(state, Kind::MLFunc), function(function),
2031 builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002032
2033 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002034
2035private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002036 MLFunction *function;
2037
2038 /// This builder intentionally shadows the builder in the base class, with a
2039 /// more specific builder type.
2040 MLFuncBuilder builder;
2041
2042 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002043 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002044 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002045 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002046 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002047 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002048};
2049} // end anonymous namespace
2050
Chris Lattner48af7d12018-07-09 19:05:38 -07002051ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002052 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002053 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002054
Chris Lattnerf7702a62018-07-23 17:30:01 -07002055 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2056 parseStatements(function)) {
2057 return ParseFailure;
2058 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002059
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002060 // TODO: store return operands in the IR.
2061 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002062
Chris Lattnerf7702a62018-07-23 17:30:01 -07002063 if (parseToken(Token::kw_return,
2064 "ML function must end with return statement") ||
2065 parseOptionalSSAUseList(dummyUseInfo) ||
2066 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2067 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002068
Chris Lattnera8e47672018-07-25 14:08:16 -07002069 getModule()->getFunctions().push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002070
Chris Lattner40746442018-07-21 14:32:09 -07002071 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002072}
2073
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002074/// For statement.
2075///
Chris Lattner48af7d12018-07-09 19:05:38 -07002076/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2077/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002078///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002079ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002080 consumeToken(Token::kw_for);
2081
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002082 // Parse induction variable
2083 if (getToken().isNot(Token::percent_identifier))
2084 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002085
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002086 // TODO: create SSA value definition from name
2087 StringRef name = getTokenSpelling().drop_front();
2088 (void)name;
2089
2090 consumeToken(Token::percent_identifier);
2091
Chris Lattnerf7702a62018-07-23 17:30:01 -07002092 if (parseToken(Token::equal, "expected ="))
2093 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002094
2095 // Parse loop bounds
2096 AffineConstantExpr *lowerBound = parseIntConstant();
2097 if (!lowerBound)
2098 return ParseFailure;
2099
Chris Lattnerf7702a62018-07-23 17:30:01 -07002100 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2101 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002102
2103 AffineConstantExpr *upperBound = parseIntConstant();
2104 if (!upperBound)
2105 return ParseFailure;
2106
2107 // Parse step
2108 AffineConstantExpr *step = nullptr;
2109 if (consumeIf(Token::kw_step)) {
2110 step = parseIntConstant();
2111 if (!step)
2112 return ParseFailure;
2113 }
2114
2115 // Create for statement.
2116 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
2117
2118 // If parsing of the for statement body fails,
2119 // MLIR contains for statement with those nested statements that have been
2120 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002121 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
2122 return ParseFailure;
2123
2124 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002125}
2126
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002127// This method is temporary workaround to parse simple loop bounds and
2128// step.
2129// TODO: remove this method once it's no longer used.
2130AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2131 if (getToken().isNot(Token::integer))
2132 return (emitError("expected non-negative integer for now"), nullptr);
2133
2134 auto val = getToken().getUInt64IntegerValue();
2135 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2136 return (emitError("constant too large for affineint"), nullptr);
2137 }
2138 consumeToken(Token::integer);
2139 return builder.getConstantExpr((int64_t)val.getValue());
2140}
2141
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002142/// If statement.
2143///
Chris Lattner48af7d12018-07-09 19:05:38 -07002144/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2145/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2146/// ml-if-stmt ::= ml-if-head
2147/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002148///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002149ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002150 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002151 if (parseToken(Token::l_paren, "expected ("))
2152 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002153
James Molloy0ff71542018-07-23 16:56:32 -07002154 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002155
Chris Lattnerf7702a62018-07-23 17:30:01 -07002156 if (parseToken(Token::r_paren, "expected )"))
2157 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002158
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002159 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002160 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002161
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002162 // When parsing of an if statement body fails, the IR contains
2163 // the if statement with the portion of the body that has been
2164 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002165 if (parseStmtBlock(thenClause))
2166 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002167
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002168 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002169 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002170 if (parseElseClause(elseClause))
2171 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002172 }
2173
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002174 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002175}
2176
2177ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2178 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002179 builder.setInsertionPoint(elseClause);
2180 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002181 }
2182
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002183 return parseStmtBlock(elseClause);
2184}
2185
2186///
2187/// Parse a list of statements ending with `return` or `}`
2188///
2189ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07002190 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
2191 ArrayRef<Type *> resultTypes,
2192 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002193 SmallVector<MLValue *, 8> stmtOperands;
2194 stmtOperands.reserve(operands.size());
2195 for (auto *op : operands)
2196 stmtOperands.push_back(cast<MLValue>(op));
2197 return builder.createOperation(name, stmtOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002198 };
2199
2200 builder.setInsertionPoint(block);
2201
2202 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2203 switch (getToken().getKind()) {
2204 default:
2205 if (parseOperation(createOpFunc))
2206 return ParseFailure;
2207 break;
2208 case Token::kw_for:
2209 if (parseForStmt())
2210 return ParseFailure;
2211 break;
2212 case Token::kw_if:
2213 if (parseIfStmt())
2214 return ParseFailure;
2215 break;
2216 } // end switch
2217 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002218
2219 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002220}
2221
2222///
2223/// Parse `{` ml-stmt* `}`
2224///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002225ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002226 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2227 parseStatements(block) ||
2228 parseToken(Token::r_brace,
2229 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002230 return ParseFailure;
2231
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002232 return ParseSuccess;
2233}
2234
Chris Lattner4c95a502018-06-23 16:03:42 -07002235//===----------------------------------------------------------------------===//
2236// Top-level entity parsing.
2237//===----------------------------------------------------------------------===//
2238
Chris Lattner2e595eb2018-07-10 10:08:27 -07002239namespace {
2240/// This parser handles entities that are only valid at the top level of the
2241/// file.
2242class ModuleParser : public Parser {
2243public:
2244 explicit ModuleParser(ParserState &state) : Parser(state) {}
2245
2246 ParseResult parseModule();
2247
2248private:
2249 ParseResult parseAffineMapDef();
2250
2251 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002252 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2253 SmallVectorImpl<StringRef> &argNames);
2254 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2255 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002256 ParseResult parseExtFunc();
2257 ParseResult parseCFGFunc();
2258 ParseResult parseMLFunc();
2259};
2260} // end anonymous namespace
2261
2262/// Affine map declaration.
2263///
2264/// affine-map-def ::= affine-map-id `=` affine-map-inline
2265///
2266ParseResult ModuleParser::parseAffineMapDef() {
2267 assert(getToken().is(Token::hash_identifier));
2268
2269 StringRef affineMapId = getTokenSpelling().drop_front();
2270
2271 // Check for redefinitions.
2272 auto *&entry = getState().affineMapDefinitions[affineMapId];
2273 if (entry)
2274 return emitError("redefinition of affine map id '" + affineMapId + "'");
2275
2276 consumeToken(Token::hash_identifier);
2277
2278 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002279 if (parseToken(Token::equal,
2280 "expected '=' in affine map outlined definition"))
2281 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002282
2283 entry = parseAffineMapInline();
2284 if (!entry)
2285 return ParseFailure;
2286
Chris Lattner2e595eb2018-07-10 10:08:27 -07002287 return ParseSuccess;
2288}
2289
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002290/// Parse a (possibly empty) list of MLFunction arguments with types.
2291///
2292/// ml-argument ::= ssa-id `:` type
2293/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2294///
2295ParseResult
2296ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2297 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002298 consumeToken(Token::l_paren);
2299
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002300 auto parseElt = [&]() -> ParseResult {
2301 // Parse argument name
2302 if (getToken().isNot(Token::percent_identifier))
2303 return emitError("expected SSA identifier");
2304
2305 StringRef name = getTokenSpelling().drop_front();
2306 consumeToken(Token::percent_identifier);
2307 argNames.push_back(name);
2308
Chris Lattnerf7702a62018-07-23 17:30:01 -07002309 if (parseToken(Token::colon, "expected ':'"))
2310 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002311
2312 // Parse argument type
2313 auto elt = parseType();
2314 if (!elt)
2315 return ParseFailure;
2316 argTypes.push_back(elt);
2317
2318 return ParseSuccess;
2319 };
2320
Chris Lattner40746442018-07-21 14:32:09 -07002321 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002322}
2323
Chris Lattner2e595eb2018-07-10 10:08:27 -07002324/// Parse a function signature, starting with a name and including the parameter
2325/// list.
2326///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002327/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002328/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2329///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002330ParseResult
2331ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2332 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002333 if (getToken().isNot(Token::at_identifier))
2334 return emitError("expected a function identifier like '@foo'");
2335
2336 name = getTokenSpelling().drop_front();
2337 consumeToken(Token::at_identifier);
2338
2339 if (getToken().isNot(Token::l_paren))
2340 return emitError("expected '(' in function signature");
2341
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002342 SmallVector<Type *, 4> argTypes;
2343 ParseResult parseResult;
2344
2345 if (argNames)
2346 parseResult = parseMLArgumentList(argTypes, *argNames);
2347 else
2348 parseResult = parseTypeList(argTypes);
2349
2350 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002351 return ParseFailure;
2352
2353 // Parse the return type if present.
2354 SmallVector<Type *, 4> results;
2355 if (consumeIf(Token::arrow)) {
2356 if (parseTypeList(results))
2357 return ParseFailure;
2358 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002359 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002360 return ParseSuccess;
2361}
2362
2363/// External function declarations.
2364///
2365/// ext-func ::= `extfunc` function-signature
2366///
2367ParseResult ModuleParser::parseExtFunc() {
2368 consumeToken(Token::kw_extfunc);
2369
2370 StringRef name;
2371 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002372 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002373 return ParseFailure;
2374
2375 // Okay, the external function definition was parsed correctly.
Chris Lattnera8e47672018-07-25 14:08:16 -07002376 getModule()->getFunctions().push_back(new ExtFunction(name, type));
Chris Lattner2e595eb2018-07-10 10:08:27 -07002377 return ParseSuccess;
2378}
2379
2380/// CFG function declarations.
2381///
2382/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2383///
2384ParseResult ModuleParser::parseCFGFunc() {
2385 consumeToken(Token::kw_cfgfunc);
2386
2387 StringRef name;
2388 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002389 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002390 return ParseFailure;
2391
2392 // Okay, the CFG function signature was parsed correctly, create the function.
2393 auto function = new CFGFunction(name, type);
2394
2395 return CFGFunctionParser(getState(), function).parseFunctionBody();
2396}
2397
2398/// ML function declarations.
2399///
2400/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2401///
2402ParseResult ModuleParser::parseMLFunc() {
2403 consumeToken(Token::kw_mlfunc);
2404
2405 StringRef name;
2406 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002407 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002408 // FIXME: Parse ML function signature (args + types)
2409 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002410
2411 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002412 return ParseFailure;
2413
2414 // Okay, the ML function signature was parsed correctly, create the function.
2415 auto function = new MLFunction(name, type);
2416
2417 return MLFunctionParser(getState(), function).parseFunctionBody();
2418}
2419
Chris Lattnere79379a2018-06-22 10:39:19 -07002420/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002421ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002422 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002423 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002424 default:
2425 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002426 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002427
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002428 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002429 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002430 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002431
2432 // If we got an error token, then the lexer already emitted an error, just
2433 // stop. Someday we could introduce error recovery if there was demand for
2434 // it.
2435 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002436 return ParseFailure;
2437
2438 case Token::hash_identifier:
2439 if (parseAffineMapDef())
2440 return ParseFailure;
2441 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002442
2443 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002444 if (parseExtFunc())
2445 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002446 break;
2447
Chris Lattner4c95a502018-06-23 16:03:42 -07002448 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002449 if (parseCFGFunc())
2450 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002451 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002452
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002453 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002454 if (parseMLFunc())
2455 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002456 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002457 }
2458 }
2459}
2460
2461//===----------------------------------------------------------------------===//
2462
Jacques Pienaar7b829702018-07-03 13:24:09 -07002463void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2464 const auto &sourceMgr = *error.getSourceMgr();
2465 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2466}
2467
Chris Lattnere79379a2018-06-22 10:39:19 -07002468/// This parses the file specified by the indicated SourceMgr and returns an
2469/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002470Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002471 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002472 // This is the result module we are parsing into.
2473 std::unique_ptr<Module> module(new Module(context));
2474
2475 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002476 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002477 if (ModuleParser(state).parseModule())
2478 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002479
2480 // Make sure the parse module has no other structural problems detected by the
2481 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002482 module->verify();
2483 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002484}