blob: b2c9bb9710e94ab72102fd179bebdbcdfe4ffa53 [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 Lattnerf7e22732018-06-22 22:03:48 -0700164 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700165 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 Type *parseTensorType();
167 Type *parseMemRefType();
168 Type *parseFunctionType();
169 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700170 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700171 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700172
Chris Lattner7121b802018-07-04 20:45:39 -0700173 // Attribute parsing.
174 Attribute *parseAttribute();
175 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
176
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700177 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700178 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700179 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700180
Chris Lattner48af7d12018-07-09 19:05:38 -0700181private:
182 // The Parser is subclassed and reinstantiated. Do not add additional
183 // non-trivial state here, add it to the ParserState class.
184 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700185};
186} // end anonymous namespace
187
188//===----------------------------------------------------------------------===//
189// Helper methods.
190//===----------------------------------------------------------------------===//
191
Chris Lattner4c95a502018-06-23 16:03:42 -0700192ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700193 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700194 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700195 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700196 return ParseFailure;
197
Chris Lattner48af7d12018-07-09 19:05:38 -0700198 auto &sourceMgr = state.lex.getSourceMgr();
199 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700200 return ParseFailure;
201}
202
Chris Lattnerf7702a62018-07-23 17:30:01 -0700203/// Consume the specified token if present and return success. On failure,
204/// output a diagnostic and return failure.
205ParseResult Parser::parseToken(Token::Kind expectedToken,
206 const Twine &message) {
207 if (consumeIf(expectedToken))
208 return ParseSuccess;
209 return emitError(message);
210}
211
Chris Lattner40746442018-07-21 14:32:09 -0700212/// Parse a comma separated list of elements that must have at least one entry
213/// in it.
214ParseResult Parser::parseCommaSeparatedList(
215 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700216 // Non-empty case starts with an element.
217 if (parseElement())
218 return ParseFailure;
219
220 // Otherwise we have a list of comma separated elements.
221 while (consumeIf(Token::comma)) {
222 if (parseElement())
223 return ParseFailure;
224 }
Chris Lattner40746442018-07-21 14:32:09 -0700225 return ParseSuccess;
226}
227
228/// Parse a comma-separated list of elements, terminated with an arbitrary
229/// token. This allows empty lists if allowEmptyList is true.
230///
231/// abstract-list ::= rightToken // if allowEmptyList == true
232/// abstract-list ::= element (',' element)* rightToken
233///
234ParseResult Parser::parseCommaSeparatedListUntil(
235 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
236 bool allowEmptyList) {
237 // Handle the empty case.
238 if (getToken().is(rightToken)) {
239 if (!allowEmptyList)
240 return emitError("expected list element");
241 consumeToken(rightToken);
242 return ParseSuccess;
243 }
244
Chris Lattnerf7702a62018-07-23 17:30:01 -0700245 if (parseCommaSeparatedList(parseElement) ||
246 parseToken(rightToken, "expected ',' or '" +
247 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700248 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250 return ParseSuccess;
251}
Chris Lattnere79379a2018-06-22 10:39:19 -0700252
253//===----------------------------------------------------------------------===//
254// Type Parsing
255//===----------------------------------------------------------------------===//
256
Chris Lattnerc3251192018-07-27 13:09:58 -0700257/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258///
Chris Lattnerc3251192018-07-27 13:09:58 -0700259/// type ::= integer-type
260/// | float-type
261/// | other-type
262/// | vector-type
263/// | tensor-type
264/// | memref-type
265/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700266///
Chris Lattnerc3251192018-07-27 13:09:58 -0700267/// float-type ::= `f16` | `bf16` | `f32` | `f64`
268/// other-type ::= `affineint` | `tf_control`
269///
270Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700271 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700272 default:
273 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700274 case Token::kw_memref:
275 return parseMemRefType();
276 case Token::kw_tensor:
277 return parseTensorType();
278 case Token::kw_vector:
279 return parseVectorType();
280 case Token::l_paren:
281 return parseFunctionType();
282 // integer-type
283 case Token::inttype: {
284 auto width = getToken().getIntTypeBitwidth();
285 if (!width.hasValue())
286 return (emitError("invalid integer width"), nullptr);
287 consumeToken(Token::inttype);
288 return builder.getIntegerType(width.getValue());
289 }
290
291 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 case Token::kw_bf16:
293 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700294 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295 case Token::kw_f16:
296 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700297 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298 case Token::kw_f32:
299 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700300 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301 case Token::kw_f64:
302 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700303 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700304
305 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700306 case Token::kw_affineint:
307 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700308 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700309 case Token::kw_tf_control:
310 consumeToken(Token::kw_tf_control);
311 return builder.getTFControlType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700312 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700313}
314
315/// Parse a vector type.
316///
317/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
318/// const-dimension-list ::= (integer-literal `x`)+
319///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700320VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321 consumeToken(Token::kw_vector);
322
Chris Lattnerf7702a62018-07-23 17:30:01 -0700323 if (parseToken(Token::less, "expected '<' in vector type"))
324 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700325
Chris Lattner48af7d12018-07-09 19:05:38 -0700326 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700327 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700328
329 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700330 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700332 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700333 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700334 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700335 dimensions.push_back(dimension.getValue());
336
337 consumeToken(Token::integer);
338
339 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700340 if (getToken().isNot(Token::bare_identifier) ||
341 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700342 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700343
344 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700345 if (getTokenSpelling().size() != 1)
346 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347
348 // Consume the 'x'.
349 consumeToken(Token::bare_identifier);
350 }
351
352 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700353 auto typeLoc = getToken().getLoc();
354 auto *elementType = parseType();
355 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700356 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700357
Chris Lattnerc3251192018-07-27 13:09:58 -0700358 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
359 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
Chris Lattnerf7e22732018-06-22 22:03:48 -0700361 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700362}
363
364/// Parse a dimension list of a tensor or memref type. This populates the
365/// dimension list, returning -1 for the '?' dimensions.
366///
367/// dimension-list-ranked ::= (dimension `x`)*
368/// dimension ::= `?` | integer-literal
369///
370ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700371 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700372 if (consumeIf(Token::question)) {
373 dimensions.push_back(-1);
374 } else {
375 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700376 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700377 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
378 return emitError("invalid dimension");
379 dimensions.push_back((int)dimension.getValue());
380 consumeToken(Token::integer);
381 }
382
383 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700384 if (getToken().isNot(Token::bare_identifier) ||
385 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700386 return emitError("expected 'x' in dimension list");
387
388 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700389 if (getTokenSpelling().size() != 1)
390 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700391
392 // Consume the 'x'.
393 consumeToken(Token::bare_identifier);
394 }
395
396 return ParseSuccess;
397}
398
399/// Parse a tensor type.
400///
401/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
402/// dimension-list ::= dimension-list-ranked | `??`
403///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700404Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700405 consumeToken(Token::kw_tensor);
406
Chris Lattnerf7702a62018-07-23 17:30:01 -0700407 if (parseToken(Token::less, "expected '<' in tensor type"))
408 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700409
410 bool isUnranked;
411 SmallVector<int, 4> dimensions;
412
413 if (consumeIf(Token::questionquestion)) {
414 isUnranked = true;
415 } else {
416 isUnranked = false;
417 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700418 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700419 }
420
421 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700422 auto typeLoc = getToken().getLoc();
423 auto *elementType = parseType();
424 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700425 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426
Chris Lattnerc3251192018-07-27 13:09:58 -0700427 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
428 !isa<VectorType>(elementType))
429 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700430
MLIR Team355ec862018-06-23 18:09:09 -0700431 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700432 return builder.getTensorType(elementType);
433 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700434}
435
436/// Parse a memref type.
437///
438/// memref-type ::= `memref` `<` dimension-list-ranked element-type
439/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
440///
441/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
442/// memory-space ::= integer-literal /* | TODO: address-space-id */
443///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700444Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700445 consumeToken(Token::kw_memref);
446
Chris Lattnerf7702a62018-07-23 17:30:01 -0700447 if (parseToken(Token::less, "expected '<' in memref type"))
448 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700449
450 SmallVector<int, 4> dimensions;
451 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700452 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700453
454 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700455 auto typeLoc = getToken().getLoc();
456 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700457 if (!elementType)
458 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700459
Chris Lattnerc3251192018-07-27 13:09:58 -0700460 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
461 !isa<VectorType>(elementType))
462 return (emitError(typeLoc, "invalid memref element type"), nullptr);
463
MLIR Team718c82f2018-07-16 09:45:22 -0700464 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700465 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700466 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700467 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700468
MLIR Team718c82f2018-07-16 09:45:22 -0700469 auto parseElt = [&]() -> ParseResult {
470 if (getToken().is(Token::integer)) {
471 // Parse memory space.
472 if (parsedMemorySpace)
473 return emitError("multiple memory spaces specified in memref type");
474 auto v = getToken().getUnsignedIntegerValue();
475 if (!v.hasValue())
476 return emitError("invalid memory space in memref type");
477 memorySpace = v.getValue();
478 consumeToken(Token::integer);
479 parsedMemorySpace = true;
480 } else {
481 // Parse affine map.
482 if (parsedMemorySpace)
483 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700484 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700485 if (affineMap == nullptr)
486 return ParseFailure;
487 affineMapComposition.push_back(affineMap);
488 }
489 return ParseSuccess;
490 };
491
Chris Lattner413db6a2018-07-25 12:55:50 -0700492 // Parse a list of mappings and address space if present.
493 if (consumeIf(Token::comma)) {
494 // Parse comma separated list of affine maps, followed by memory space.
495 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
496 /*allowEmptyList=*/false)) {
497 return nullptr;
498 }
499 } else {
500 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
501 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700502 }
MLIR Team718c82f2018-07-16 09:45:22 -0700503
504 return MemRefType::get(dimensions, elementType, affineMapComposition,
505 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700506}
507
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700508/// Parse a function type.
509///
510/// function-type ::= type-list-parens `->` type-list
511///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700512Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700513 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700514
Chris Lattnerf7702a62018-07-23 17:30:01 -0700515 SmallVector<Type *, 4> arguments, results;
516 if (parseTypeList(arguments) ||
517 parseToken(Token::arrow, "expected '->' in function type") ||
518 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700519 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700520
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700521 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700522}
523
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700524
Chris Lattner1604e472018-07-23 08:42:19 -0700525/// Parse a list of types without an enclosing parenthesis. The list must have
526/// at least one member.
527///
528/// type-list-no-parens ::= type (`,` type)*
529///
530ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
531 auto parseElt = [&]() -> ParseResult {
532 auto elt = parseType();
533 elements.push_back(elt);
534 return elt ? ParseSuccess : ParseFailure;
535 };
536
537 return parseCommaSeparatedList(parseElt);
538}
539
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700540/// Parse a "type list", which is a singular type, or a parenthesized list of
541/// types.
542///
543/// type-list ::= type-list-parens | type
544/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700545/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700546///
James Molloy0ff71542018-07-23 16:56:32 -0700547ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700548 auto parseElt = [&]() -> ParseResult {
549 auto elt = parseType();
550 elements.push_back(elt);
551 return elt ? ParseSuccess : ParseFailure;
552 };
553
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700554 // If there is no parens, then it must be a singular type.
555 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700556 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700557
Chris Lattner40746442018-07-21 14:32:09 -0700558 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700559 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700560
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700561 return ParseSuccess;
562}
563
Chris Lattner4c95a502018-06-23 16:03:42 -0700564//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700565// Attribute parsing.
566//===----------------------------------------------------------------------===//
567
Chris Lattner7121b802018-07-04 20:45:39 -0700568/// Attribute parsing.
569///
570/// attribute-value ::= bool-literal
571/// | integer-literal
572/// | float-literal
573/// | string-literal
574/// | `[` (attribute-value (`,` attribute-value)*)? `]`
575///
576Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700577 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700578 case Token::kw_true:
579 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700580 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700581 case Token::kw_false:
582 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700583 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700584
585 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700586 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700587 if (!val.hasValue() || (int64_t)val.getValue() < 0)
588 return (emitError("integer too large for attribute"), nullptr);
589 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700590 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700591 }
592
593 case Token::minus: {
594 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700595 if (getToken().is(Token::integer)) {
596 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700597 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
598 return (emitError("integer too large for attribute"), nullptr);
599 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700600 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700601 }
602
603 return (emitError("expected constant integer or floating point value"),
604 nullptr);
605 }
606
607 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700608 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700609 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700610 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700611 }
612
Chris Lattner85ee1512018-07-25 11:15:20 -0700613 case Token::l_square: {
614 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700615 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700616
617 auto parseElt = [&]() -> ParseResult {
618 elements.push_back(parseAttribute());
619 return elements.back() ? ParseSuccess : ParseFailure;
620 };
621
Chris Lattner85ee1512018-07-25 11:15:20 -0700622 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700623 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700624 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700625 }
626 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700627 // Try to parse affine map reference.
James Molloy0ff71542018-07-23 16:56:32 -0700628 auto *affineMap = parseAffineMapReference();
MLIR Teamb61885d2018-07-18 16:29:21 -0700629 if (affineMap != nullptr)
630 return builder.getAffineMapAttr(affineMap);
631
Chris Lattner7121b802018-07-04 20:45:39 -0700632 // TODO: Handle floating point.
633 return (emitError("expected constant attribute value"), nullptr);
634 }
635}
636
Chris Lattner7121b802018-07-04 20:45:39 -0700637/// Attribute dictionary.
638///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700639/// attribute-dict ::= `{` `}`
640/// | `{` attribute-entry (`,` attribute-entry)* `}`
641/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700642///
James Molloy0ff71542018-07-23 16:56:32 -0700643ParseResult
644Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700645 consumeToken(Token::l_brace);
646
647 auto parseElt = [&]() -> ParseResult {
648 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700649 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
650 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700651 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700652 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700653 consumeToken();
654
Chris Lattnerf7702a62018-07-23 17:30:01 -0700655 if (parseToken(Token::colon, "expected ':' in attribute list"))
656 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700657
658 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700659 if (!attr)
660 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700661
662 attributes.push_back({nameId, attr});
663 return ParseSuccess;
664 };
665
Chris Lattner40746442018-07-21 14:32:09 -0700666 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700667 return ParseFailure;
668
669 return ParseSuccess;
670}
671
672//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700673// Polyhedral structures.
674//===----------------------------------------------------------------------===//
675
Chris Lattner2e595eb2018-07-10 10:08:27 -0700676/// Lower precedence ops (all at the same precedence level). LNoOp is false in
677/// the boolean sense.
678enum AffineLowPrecOp {
679 /// Null value.
680 LNoOp,
681 Add,
682 Sub
683};
MLIR Teamf85a6262018-06-27 11:03:08 -0700684
Chris Lattner2e595eb2018-07-10 10:08:27 -0700685/// Higher precedence ops - all at the same precedence level. HNoOp is false in
686/// the boolean sense.
687enum AffineHighPrecOp {
688 /// Null value.
689 HNoOp,
690 Mul,
691 FloorDiv,
692 CeilDiv,
693 Mod
694};
Chris Lattner7121b802018-07-04 20:45:39 -0700695
Chris Lattner2e595eb2018-07-10 10:08:27 -0700696namespace {
697/// This is a specialized parser for AffineMap's, maintaining the state
698/// transient to their bodies.
699class AffineMapParser : public Parser {
700public:
701 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700702
Chris Lattner2e595eb2018-07-10 10:08:27 -0700703 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700704
Chris Lattner2e595eb2018-07-10 10:08:27 -0700705private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700706 // Binary affine op parsing.
707 AffineLowPrecOp consumeIfLowPrecOp();
708 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700709
Chris Lattner2e595eb2018-07-10 10:08:27 -0700710 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700711 ParseResult parseDimIdList(unsigned &numDims);
712 ParseResult parseSymbolIdList(unsigned &numSymbols);
713 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700714
715 AffineExpr *parseAffineExpr();
716 AffineExpr *parseParentheticalExpr();
717 AffineExpr *parseNegateExpression(AffineExpr *lhs);
718 AffineExpr *parseIntegerExpr();
719 AffineExpr *parseBareIdExpr();
720
721 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700722 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700723 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
724 AffineExpr *rhs);
725 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
726 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
727 AffineLowPrecOp llhsOp);
728 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700729 AffineHighPrecOp llhsOp,
730 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700731
732private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700733 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700734};
735} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700736
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700737/// Create an affine binary high precedence op expression (mul's, div's, mod).
738/// opLoc is the location of the op token to be used to report errors
739/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700740AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
741 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700742 AffineExpr *rhs,
743 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700744 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700745 switch (op) {
746 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700747 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700748 emitError(opLoc, "non-affine expression: at least one of the multiply "
749 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700750 return nullptr;
751 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700752 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700753 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700754 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700755 emitError(opLoc, "non-affine expression: right operand of floordiv "
756 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700757 return nullptr;
758 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700759 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700760 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700761 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700762 emitError(opLoc, "non-affine expression: right operand of ceildiv "
763 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700764 return nullptr;
765 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700766 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700767 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700768 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700769 emitError(opLoc, "non-affine expression: right operand of mod "
770 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700771 return nullptr;
772 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700773 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700774 case HNoOp:
775 llvm_unreachable("can't create affine expression for null high prec op");
776 return nullptr;
777 }
778}
779
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700780/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700781AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
782 AffineExpr *lhs,
783 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700784 switch (op) {
785 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700786 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700787 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700788 return builder.getAddExpr(
789 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700790 case AffineLowPrecOp::LNoOp:
791 llvm_unreachable("can't create affine expression for null low prec op");
792 return nullptr;
793 }
794}
795
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700796/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700797/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700798AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700799 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700800 case Token::plus:
801 consumeToken(Token::plus);
802 return AffineLowPrecOp::Add;
803 case Token::minus:
804 consumeToken(Token::minus);
805 return AffineLowPrecOp::Sub;
806 default:
807 return AffineLowPrecOp::LNoOp;
808 }
809}
810
811/// Consume this token if it is a higher precedence affine op (there are only
812/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700813AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700814 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700815 case Token::star:
816 consumeToken(Token::star);
817 return Mul;
818 case Token::kw_floordiv:
819 consumeToken(Token::kw_floordiv);
820 return FloorDiv;
821 case Token::kw_ceildiv:
822 consumeToken(Token::kw_ceildiv);
823 return CeilDiv;
824 case Token::kw_mod:
825 consumeToken(Token::kw_mod);
826 return Mod;
827 default:
828 return HNoOp;
829 }
830}
831
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700832/// Parse a high precedence op expression list: mul, div, and mod are high
833/// precedence binary ops, i.e., parse a
834/// expr_1 op_1 expr_2 op_2 ... expr_n
835/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
836/// All affine binary ops are left associative.
837/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
838/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700839/// null. llhsOpLoc is the location of the llhsOp token that will be used to
840/// report an error for non-conforming expressions.
841AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
842 AffineHighPrecOp llhsOp,
843 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700844 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700845 if (!lhs)
846 return nullptr;
847
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700848 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700849 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700850 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700851 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700852 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853 if (!expr)
854 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700855 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856 }
857 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700858 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700859 }
860
861 // This is the last operand in this expression.
862 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700864
865 // No llhs, 'lhs' itself is the expression.
866 return lhs;
867}
868
869/// Parse an affine expression inside parentheses.
870///
871/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700872AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700873 if (parseToken(Token::l_paren, "expected '('"))
874 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700875 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700876 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700877
Chris Lattner2e595eb2018-07-10 10:08:27 -0700878 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700879 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700880 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700881 if (parseToken(Token::r_paren, "expected ')'"))
882 return nullptr;
883
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884 return expr;
885}
886
887/// Parse the negation expression.
888///
889/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700890AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700891 if (parseToken(Token::minus, "expected '-'"))
892 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700893
Chris Lattner2e595eb2018-07-10 10:08:27 -0700894 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700895 // Since negation has the highest precedence of all ops (including high
896 // precedence ops) but lower than parentheses, we are only going to use
897 // parseAffineOperandExpr instead of parseAffineExpr here.
898 if (!operand)
899 // Extra error message although parseAffineOperandExpr would have
900 // complained. Leads to a better diagnostic.
901 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700902 auto *minusOne = builder.getConstantExpr(-1);
903 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700904}
905
906/// Parse a bare id that may appear in an affine expression.
907///
908/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700909AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700910 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700911 return (emitError("expected bare identifier"), nullptr);
912
Chris Lattner48af7d12018-07-09 19:05:38 -0700913 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700914 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700915 if (entry.first == sRef) {
916 consumeToken(Token::bare_identifier);
917 return entry.second;
918 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700919 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700920
921 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700922}
923
924/// Parse a positive integral constant appearing in an affine expression.
925///
926/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700927AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700928 // No need to handle negative numbers separately here. They are naturally
929 // handled via the unary negation operator, although (FIXME) MININT_64 still
930 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700931 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700932 return (emitError("expected integer"), nullptr);
933
Chris Lattner48af7d12018-07-09 19:05:38 -0700934 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700935 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
936 return (emitError("constant too large for affineint"), nullptr);
937 }
938 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700939 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940}
941
942/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700943/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
944/// operator, the rhs of which is being parsed. This is used to determine
945/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946// Eg: for an expression without parentheses (like i + j + k + l), each
947// of the four identifiers is an operand. For i + j*k + l, j*k is not an
948// operand expression, it's an op expression and will be parsed via
949// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
950// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700951AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700952 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700954 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700955 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700956 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700957 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700958 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700959 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700960 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700961 case Token::kw_ceildiv:
962 case Token::kw_floordiv:
963 case Token::kw_mod:
964 case Token::plus:
965 case Token::star:
966 if (lhs)
967 emitError("missing right operand of binary operator");
968 else
969 emitError("missing left operand of binary operator");
970 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700971 default:
972 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700973 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700974 else
975 emitError("expected affine expression");
976 return nullptr;
977 }
978}
979
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700980/// Parse affine expressions that are bare-id's, integer constants,
981/// parenthetical affine expressions, and affine op expressions that are a
982/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700983///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700984/// All binary op's associate from left to right.
985///
986/// {add, sub} have lower precedence than {mul, div, and mod}.
987///
Uday Bondhugula76345202018-07-09 13:47:52 -0700988/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
989/// ceildiv, and mod are at the same higher precedence level. Negation has
990/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700991///
992/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700993/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
994/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
995/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700996/// associativity.
997///
998/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700999/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1000/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001001AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1002 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001003 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001004 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001005 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001006
1007 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001008 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001010 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001011 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001012 }
1013 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001015 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001016 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001017 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001018 // We have a higher precedence op here. Get the rhs operand for the llhs
1019 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001020 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001021 if (!highRes)
1022 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001023
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001024 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001025 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001026 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001027 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001028
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001029 // Recurse for subsequent low prec op's after the affine high prec op
1030 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001031 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1032 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001033 return expr;
1034 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001035 // Last operand in the expression list.
1036 if (llhs)
1037 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1038 // No llhs, 'lhs' itself is the expression.
1039 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001040}
1041
1042/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001043/// affine-expr ::= `(` affine-expr `)`
1044/// | `-` affine-expr
1045/// | affine-expr `+` affine-expr
1046/// | affine-expr `-` affine-expr
1047/// | affine-expr `*` affine-expr
1048/// | affine-expr `floordiv` affine-expr
1049/// | affine-expr `ceildiv` affine-expr
1050/// | affine-expr `mod` affine-expr
1051/// | bare-id
1052/// | integer-literal
1053///
1054/// Additional conditions are checked depending on the production. For eg., one
1055/// of the operands for `*` has to be either constant/symbolic; the second
1056/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001057AffineExpr *AffineMapParser::parseAffineExpr() {
1058 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001059}
1060
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001061/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001062/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001063/// identifier.
1064ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001065 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001066 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001067
1068 auto name = getTokenSpelling();
1069 for (auto entry : dimsAndSymbols) {
1070 if (entry.first == name)
1071 return emitError("redefinition of identifier '" + Twine(name) + "'");
1072 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001073 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001074
1075 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001076 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001077}
1078
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001079/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001080ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1081 consumeToken(Token::l_square);
1082 auto parseElt = [&]() -> ParseResult {
1083 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1084 return parseIdentifierDefinition(symbol);
1085 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001086 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001087}
1088
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001089/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001090ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001091 if (parseToken(Token::l_paren,
1092 "expected '(' at start of dimensional identifiers list"))
1093 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001094
Chris Lattner413db6a2018-07-25 12:55:50 -07001095 auto parseElt = [&]() -> ParseResult {
1096 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1097 return parseIdentifierDefinition(dimension);
1098 };
Chris Lattner40746442018-07-21 14:32:09 -07001099 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001100}
1101
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001102/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001103///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001104/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1105/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1106/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001107///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001108/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001109AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001110 unsigned numDims = 0, numSymbols = 0;
1111
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001112 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001113 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001114 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001115
1116 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001117 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001118 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001119 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001120 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001121
1122 if (parseToken(Token::arrow, "expected '->' or '['") ||
1123 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001124 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001125
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001126 SmallVector<AffineExpr *, 4> exprs;
1127 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001128 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001129 ParseResult res = elt ? ParseSuccess : ParseFailure;
1130 exprs.push_back(elt);
1131 return res;
1132 };
1133
1134 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001135 // affine expressions); the list cannot be empty.
1136 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001137 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001138 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001139
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001140 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001141 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1142 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1143 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001144 // TODO: check if sizes are non-negative whenever they are constant.
1145 SmallVector<AffineExpr *, 4> rangeSizes;
1146 if (consumeIf(Token::kw_size)) {
1147 // Location of the l_paren token (if it exists) for error reporting later.
1148 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001149 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1150 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001151
1152 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001153 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001154 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001155 if (!elt)
1156 return ParseFailure;
1157
1158 if (!elt->isSymbolicOrConstant())
1159 return emitError(loc,
1160 "size expressions cannot refer to dimension values");
1161
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001162 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001163 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001164 };
1165
Chris Lattner40746442018-07-21 14:32:09 -07001166 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001167 return nullptr;
1168 if (exprs.size() > rangeSizes.size())
1169 return (emitError(loc, "fewer range sizes than range expressions"),
1170 nullptr);
1171 if (exprs.size() < rangeSizes.size())
1172 return (emitError(loc, "more range sizes than range expressions"),
1173 nullptr);
1174 }
1175
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001176 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001177 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001178}
1179
Chris Lattner2e595eb2018-07-10 10:08:27 -07001180AffineMap *Parser::parseAffineMapInline() {
1181 return AffineMapParser(state).parseAffineMapInline();
1182}
1183
MLIR Team718c82f2018-07-16 09:45:22 -07001184AffineMap *Parser::parseAffineMapReference() {
1185 if (getToken().is(Token::hash_identifier)) {
1186 // Parse affine map identifier and verify that it exists.
1187 StringRef affineMapId = getTokenSpelling().drop_front();
1188 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1189 return (emitError("undefined affine map id '" + affineMapId + "'"),
1190 nullptr);
1191 consumeToken(Token::hash_identifier);
1192 return getState().affineMapDefinitions[affineMapId];
1193 }
1194 // Try to parse inline affine map.
1195 return parseAffineMapInline();
1196}
1197
MLIR Teamf85a6262018-06-27 11:03:08 -07001198//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001199// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001200//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001201
Chris Lattner7f9cc272018-07-19 08:35:28 -07001202namespace {
1203/// This class contains parser state that is common across CFG and ML functions,
1204/// notably for dealing with operations and SSA values.
1205class FunctionParser : public Parser {
1206public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001207 enum class Kind { CFGFunc, MLFunc };
1208
1209 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001210
Chris Lattner6119d382018-07-20 18:41:34 -07001211 /// After the function is finished parsing, this function checks to see if
1212 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001213 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001214
1215 /// This represents a use of an SSA value in the program. The first two
1216 /// entries in the tuple are the name and result number of a reference. The
1217 /// third is the location of the reference, which is used in case this ends up
1218 /// being a use of an undefined value.
1219 struct SSAUseInfo {
1220 StringRef name; // Value name, e.g. %42 or %abc
1221 unsigned number; // Number, specified with #12
1222 SMLoc loc; // Location of first definition or use.
1223 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001224
1225 /// Given a reference to an SSA value and its type, return a reference. This
1226 /// returns null on failure.
1227 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1228
1229 /// Register a definition of a value with the symbol table.
1230 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1231
1232 // SSA parsing productions.
1233 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001234 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001235
1236 template <typename ResultType>
1237 ResultType parseSSADefOrUseAndType(
1238 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1239
1240 SSAValue *parseSSAUseAndType() {
1241 return parseSSADefOrUseAndType<SSAValue *>(
1242 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1243 return resolveSSAUse(useInfo, type);
1244 });
1245 }
Chris Lattner40746442018-07-21 14:32:09 -07001246
1247 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001248 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001249 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1250 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001251
1252 // Operations
1253 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001254 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1255 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001256
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001257protected:
1258 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1259
Chris Lattner7f9cc272018-07-19 08:35:28 -07001260private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001261 /// Kind indicates if this is CFG or ML function parser.
1262 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001263 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001264 /// their name. This has one entry per result number.
1265 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1266
1267 /// These are all of the placeholders we've made along with the location of
1268 /// their first reference, to allow checking for use of undefined values.
1269 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1270
1271 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1272
1273 /// Return true if this is a forward reference.
1274 bool isForwardReferencePlaceholder(SSAValue *value) {
1275 return forwardReferencePlaceholders.count(value);
1276 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001277};
1278} // end anonymous namespace
1279
Chris Lattner6119d382018-07-20 18:41:34 -07001280/// Create and remember a new placeholder for a forward reference.
1281SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1282 Type *type) {
1283 // Forward references are always created as instructions, even in ML
1284 // functions, because we just need something with a def/use chain.
1285 //
1286 // We create these placeholders as having an empty name, which we know cannot
1287 // be created through normal user input, allowing us to distinguish them.
1288 auto name = Identifier::get("placeholder", getContext());
1289 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1290 getContext());
1291 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1292 return inst->getResult(0);
1293}
1294
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001295/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001296/// it specifies. This returns null on failure.
1297SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001298 auto &entries = values[useInfo.name];
1299
Chris Lattner7f9cc272018-07-19 08:35:28 -07001300 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001301 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1302 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001303 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001304 if (result->getType() == type)
1305 return result;
1306
Chris Lattner6119d382018-07-20 18:41:34 -07001307 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1308 "' expects different type than prior uses");
1309 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001310 return nullptr;
1311 }
1312
Chris Lattner6119d382018-07-20 18:41:34 -07001313 // Make sure we have enough slots for this.
1314 if (entries.size() <= useInfo.number)
1315 entries.resize(useInfo.number + 1);
1316
1317 // If the value has already been defined and this is an overly large result
1318 // number, diagnose that.
1319 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1320 return (emitError(useInfo.loc, "reference to invalid result number"),
1321 nullptr);
1322
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001323 if (getKind() == Kind::MLFunc)
1324 return (
1325 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1326 nullptr);
1327
1328 // Otherwise, this is a forward reference. If we are in ML function return
1329 // an error. In CFG function, create a placeholder and remember
Chris Lattner6119d382018-07-20 18:41:34 -07001330 // that we did so.
1331 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1332 entries[useInfo.number].first = result;
1333 entries[useInfo.number].second = useInfo.loc;
1334 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001335}
1336
1337/// Register a definition of a value with the symbol table.
1338ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001339 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001340
Chris Lattner6119d382018-07-20 18:41:34 -07001341 // Make sure there is a slot for this value.
1342 if (entries.size() <= useInfo.number)
1343 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001344
Chris Lattner6119d382018-07-20 18:41:34 -07001345 // If we already have an entry for this, check to see if it was a definition
1346 // or a forward reference.
1347 if (auto *existing = entries[useInfo.number].first) {
1348 if (!isForwardReferencePlaceholder(existing)) {
1349 emitError(useInfo.loc,
1350 "redefinition of SSA value '" + useInfo.name + "'");
1351 return emitError(entries[useInfo.number].second,
1352 "previously defined here");
1353 }
1354
1355 // If it was a forward reference, update everything that used it to use the
1356 // actual definition instead, delete the forward ref, and remove it from our
1357 // set of forward references we track.
1358 existing->replaceAllUsesWith(value);
1359 existing->getDefiningInst()->destroy();
1360 forwardReferencePlaceholders.erase(existing);
1361 }
1362
1363 entries[useInfo.number].first = value;
1364 entries[useInfo.number].second = useInfo.loc;
1365 return ParseSuccess;
1366}
1367
1368/// After the function is finished parsing, this function checks to see if
1369/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001370ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001371 // Check for any forward references that are left. If we find any, error out.
1372 if (!forwardReferencePlaceholders.empty()) {
1373 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1374 // Iteration over the map isn't determinstic, so sort by source location.
1375 for (auto entry : forwardReferencePlaceholders)
1376 errors.push_back({entry.second.getPointer(), entry.first});
1377 llvm::array_pod_sort(errors.begin(), errors.end());
1378
1379 for (auto entry : errors)
1380 emitError(SMLoc::getFromPointer(entry.first),
1381 "use of undeclared SSA value name");
1382 return ParseFailure;
1383 }
1384
Chris Lattner40746442018-07-21 14:32:09 -07001385 // Run the verifier on this function. If an error is detected, report it.
1386 std::string errorString;
1387 if (func->verify(&errorString))
1388 return emitError(loc, errorString);
1389
Chris Lattner6119d382018-07-20 18:41:34 -07001390 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001391}
1392
Chris Lattner78276e32018-07-07 15:48:26 -07001393/// Parse a SSA operand for an instruction or statement.
1394///
James Molloy61a656c2018-07-22 15:45:24 -07001395/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001396///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001397ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001398 result.name = getTokenSpelling();
1399 result.number = 0;
1400 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001401 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1402 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001403
1404 // If we have an affine map ID, it is a result number.
1405 if (getToken().is(Token::hash_identifier)) {
1406 if (auto value = getToken().getHashIdentifierNumber())
1407 result.number = value.getValue();
1408 else
1409 return emitError("invalid SSA value result number");
1410 consumeToken(Token::hash_identifier);
1411 }
1412
Chris Lattner7f9cc272018-07-19 08:35:28 -07001413 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001414}
1415
1416/// Parse a (possibly empty) list of SSA operands.
1417///
1418/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1419/// ssa-use-list-opt ::= ssa-use-list?
1420///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001421ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001422FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001423 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001424 return ParseSuccess;
1425 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001426 SSAUseInfo result;
1427 if (parseSSAUse(result))
1428 return ParseFailure;
1429 results.push_back(result);
1430 return ParseSuccess;
1431 });
Chris Lattner78276e32018-07-07 15:48:26 -07001432}
1433
1434/// Parse an SSA use with an associated type.
1435///
1436/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001437template <typename ResultType>
1438ResultType FunctionParser::parseSSADefOrUseAndType(
1439 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001440
Chris Lattnerf7702a62018-07-23 17:30:01 -07001441 SSAUseInfo useInfo;
1442 if (parseSSAUse(useInfo) ||
1443 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1444 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001445
Chris Lattner7f9cc272018-07-19 08:35:28 -07001446 auto *type = parseType();
1447 if (!type)
1448 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001449
James Molloy61a656c2018-07-22 15:45:24 -07001450 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001451}
1452
Chris Lattner2c402672018-07-23 11:56:17 -07001453/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1454/// followed by a type list. If hasParens is true, then the operands are
1455/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001456///
Chris Lattner2c402672018-07-23 11:56:17 -07001457/// ssa-use-and-type-list[parens]
1458/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1459///
1460/// ssa-use-and-type-list[!parens]
1461/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001462///
Chris Lattner40746442018-07-21 14:32:09 -07001463template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001464ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001465 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1466
1467 // If we are in the parenthesized form and no paren exists, then we succeed
1468 // with an empty list.
1469 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001470 return ParseSuccess;
1471
Chris Lattner2c402672018-07-23 11:56:17 -07001472 SmallVector<SSAUseInfo, 4> valueIDs;
1473 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001474 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001475
1476 if (isParenthesized && !consumeIf(Token::r_paren))
1477 return emitError("expected ')' in operand list");
1478
1479 // If there were no operands, then there is no colon or type lists.
1480 if (valueIDs.empty())
1481 return ParseSuccess;
1482
Chris Lattner2c402672018-07-23 11:56:17 -07001483 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001484 if (parseToken(Token::colon, "expected ':' in operand list") ||
1485 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001486 return ParseFailure;
1487
1488 if (valueIDs.size() != types.size())
1489 return emitError("expected " + Twine(valueIDs.size()) +
1490 " types to match operand list");
1491
1492 results.reserve(valueIDs.size());
1493 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1494 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1495 results.push_back(cast<ValueTy>(value));
1496 else
1497 return ParseFailure;
1498 }
1499
1500 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001501}
1502
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001503/// Parse the CFG or MLFunc operation.
1504///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001505/// operation ::=
1506/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1507/// `:` function-type
1508///
1509ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001510FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001511 auto loc = getToken().getLoc();
1512
1513 StringRef resultID;
1514 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001515 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001516 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001517 if (parseToken(Token::equal, "expected '=' after SSA name"))
1518 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001519 }
1520
Chris Lattner85ee1512018-07-25 11:15:20 -07001521 Operation *op;
1522 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1523 op = parseCustomOperation(createOpFunc);
1524 else if (getToken().is(Token::string))
1525 op = parseVerboseOperation(createOpFunc);
1526 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001527 return emitError("expected operation name in quotes");
1528
Chris Lattner85ee1512018-07-25 11:15:20 -07001529 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001530 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001531 return ParseFailure;
1532
1533 // We just parsed an operation. If it is a recognized one, verify that it
1534 // is structurally as we expect. If not, produce an error with a reasonable
1535 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001536 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1537 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001538 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001539 }
1540
Chris Lattner7f9cc272018-07-19 08:35:28 -07001541 // If the instruction had a name, register it.
1542 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001543 if (op->getNumResults() == 0)
1544 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001545
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001546 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
1547 addDefinition({resultID, i, loc}, op->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001548 }
1549
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001550 return ParseSuccess;
1551}
Chris Lattnere79379a2018-06-22 10:39:19 -07001552
Chris Lattner85ee1512018-07-25 11:15:20 -07001553Operation *FunctionParser::parseVerboseOperation(
1554 const CreateOperationFunction &createOpFunc) {
1555 auto name = getToken().getStringValue();
1556 if (name.empty())
1557 return (emitError("empty operation name is invalid"), nullptr);
1558
1559 consumeToken(Token::string);
1560
1561 // Parse the operand list.
1562 SmallVector<SSAUseInfo, 8> operandInfos;
1563
1564 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1565 parseOptionalSSAUseList(operandInfos) ||
1566 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1567 return nullptr;
1568 }
1569
1570 SmallVector<NamedAttribute, 4> attributes;
1571 if (getToken().is(Token::l_brace)) {
1572 if (parseAttributeDict(attributes))
1573 return nullptr;
1574 }
1575
1576 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1577 return nullptr;
1578
1579 auto typeLoc = getToken().getLoc();
1580 auto type = parseType();
1581 if (!type)
1582 return nullptr;
1583 auto fnType = dyn_cast<FunctionType>(type);
1584 if (!fnType)
1585 return (emitError(typeLoc, "expected function type"), nullptr);
1586
1587 // Check that we have the right number of types for the operands.
1588 auto operandTypes = fnType->getInputs();
1589 if (operandTypes.size() != operandInfos.size()) {
1590 auto plural = "s"[operandInfos.size() == 1];
1591 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1592 " operand type" + plural + " but had " +
1593 llvm::utostr(operandTypes.size())),
1594 nullptr);
1595 }
1596
1597 // Resolve all of the operands.
1598 SmallVector<SSAValue *, 8> operands;
1599 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1600 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1601 if (!operands.back())
1602 return nullptr;
1603 }
1604
1605 auto nameId = builder.getIdentifier(name);
1606 return createOpFunc(nameId, operands, fnType->getResults(), attributes);
1607}
1608
1609namespace {
1610class CustomOpAsmParser : public OpAsmParser {
1611public:
1612 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1613 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1614
1615 /// This is an internal helper to parser a colon, we don't want to expose
1616 /// this to clients.
1617 bool internalParseColon(llvm::SMLoc *loc) {
1618 if (loc)
1619 *loc = parser.getToken().getLoc();
1620 return parser.parseToken(Token::colon, "expected ':'");
1621 }
1622
1623 //===--------------------------------------------------------------------===//
1624 // High level parsing methods.
1625 //===--------------------------------------------------------------------===//
1626
1627 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1628 if (loc)
1629 *loc = parser.getToken().getLoc();
1630 return parser.parseToken(Token::comma, "expected ','");
1631 }
1632
1633 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1634 return internalParseColon(loc) || !(result = parser.parseType());
1635 }
1636
1637 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1638 llvm::SMLoc *loc = nullptr) override {
1639 if (internalParseColon(loc))
1640 return true;
1641
1642 do {
1643 if (auto *type = parser.parseType())
1644 result.push_back(type);
1645 else
1646 return true;
1647
1648 } while (parser.consumeIf(Token::comma));
1649 return false;
1650 }
1651
1652 bool parseAttribute(Attribute *&result, llvm::SMLoc *loc = nullptr) override {
1653 if (loc)
1654 *loc = parser.getToken().getLoc();
1655 result = parser.parseAttribute();
1656 return result == nullptr;
1657 }
1658
1659 bool parseOperand(OperandType &result) override {
1660 FunctionParser::SSAUseInfo useInfo;
1661 if (parser.parseSSAUse(useInfo))
1662 return true;
1663
1664 result = {useInfo.loc, useInfo.name, useInfo.number};
1665 return false;
1666 }
1667
1668 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1669 int requiredOperandCount = -1,
1670 Delimeter delimeter = Delimeter::NoDelimeter) override {
1671 auto startLoc = parser.getToken().getLoc();
1672
1673 // Handle delimeters.
1674 switch (delimeter) {
1675 case Delimeter::NoDelimeter:
1676 break;
1677 case Delimeter::ParenDelimeter:
1678 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1679 return true;
1680 break;
1681 case Delimeter::SquareDelimeter:
1682 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1683 return true;
1684 break;
1685 }
1686
1687 // Check for zero operands.
1688 if (parser.getToken().is(Token::percent_identifier)) {
1689 do {
1690 OperandType operand;
1691 if (parseOperand(operand))
1692 return true;
1693 result.push_back(operand);
1694 } while (parser.consumeIf(Token::comma));
1695 }
1696
1697 // Handle delimeters.
1698 switch (delimeter) {
1699 case Delimeter::NoDelimeter:
1700 break;
1701 case Delimeter::ParenDelimeter:
1702 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1703 return true;
1704 break;
1705 case Delimeter::SquareDelimeter:
1706 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1707 return true;
1708 break;
1709 }
1710
1711 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1712 emitError(startLoc,
1713 "expected " + Twine(requiredOperandCount) + " operands");
1714 return false;
1715 }
1716
1717 //===--------------------------------------------------------------------===//
1718 // Methods for interacting with the parser
1719 //===--------------------------------------------------------------------===//
1720
1721 Builder &getBuilder() const override { return parser.builder; }
1722
1723 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1724
1725 bool resolveOperand(OperandType operand, Type *type,
1726 SSAValue *&result) override {
1727 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1728 operand.location};
1729 result = parser.resolveSSAUse(operandInfo, type);
1730 return result == nullptr;
1731 }
1732
1733 /// Emit a diagnostic at the specified location.
1734 void emitError(llvm::SMLoc loc, const Twine &message) override {
1735 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1736 emittedError = true;
1737 }
1738
1739 bool didEmitError() const { return emittedError; }
1740
1741private:
1742 SMLoc nameLoc;
1743 StringRef opName;
1744 FunctionParser &parser;
1745 bool emittedError = false;
1746};
1747} // end anonymous namespace.
1748
1749Operation *FunctionParser::parseCustomOperation(
1750 const CreateOperationFunction &createOpFunc) {
1751 auto opLoc = getToken().getLoc();
1752 auto opName = getTokenSpelling();
1753 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1754
1755 auto *opDefinition = getOperationSet().lookup(opName);
1756 if (!opDefinition) {
1757 opAsmParser.emitError(opLoc, "is unknown");
1758 return nullptr;
1759 }
1760
1761 consumeToken();
1762
1763 // Have the op implementation take a crack and parsing this.
1764 auto result = opDefinition->parseAssembly(&opAsmParser);
1765
1766 // If it emitted an error, we failed.
1767 if (opAsmParser.didEmitError())
1768 return nullptr;
1769
1770 // Otherwise, we succeeded. Use the state it parsed as our op information.
1771 auto nameId = builder.getIdentifier(opName);
1772 return createOpFunc(nameId, result.operands, result.types, result.attributes);
1773}
1774
Chris Lattner48af7d12018-07-09 19:05:38 -07001775//===----------------------------------------------------------------------===//
1776// CFG Functions
1777//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001778
Chris Lattner4c95a502018-06-23 16:03:42 -07001779namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001780/// This is a specialized parser for CFGFunction's, maintaining the state
1781/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001782class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001783public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001784 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001785 : FunctionParser(state, Kind::CFGFunc), function(function),
1786 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001787
1788 ParseResult parseFunctionBody();
1789
1790private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001791 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001792 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001793
1794 /// This builder intentionally shadows the builder in the base class, with a
1795 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001796 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001797
Chris Lattner4c95a502018-06-23 16:03:42 -07001798 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001799 /// already exist. The location specified is the point of use, which allows
1800 /// us to diagnose references to blocks that are not defined precisely.
1801 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1802 auto &blockAndLoc = blocksByName[name];
1803 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001804 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001805 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001806 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001807 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001808 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001809
James Molloy61a656c2018-07-22 15:45:24 -07001810 ParseResult
1811 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1812 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001813 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1814 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001815
Chris Lattner48af7d12018-07-09 19:05:38 -07001816 ParseResult parseBasicBlock();
1817 OperationInst *parseCFGOperation();
1818 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001819};
1820} // end anonymous namespace
1821
James Molloy61a656c2018-07-22 15:45:24 -07001822/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001823/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001824///
1825/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1826///
1827ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1828 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1829 if (getToken().is(Token::r_brace))
1830 return ParseSuccess;
1831
1832 return parseCommaSeparatedList([&]() -> ParseResult {
1833 auto type = parseSSADefOrUseAndType<Type *>(
1834 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1835 BBArgument *arg = owner->addArgument(type);
1836 if (addDefinition(useInfo, arg) == ParseFailure)
1837 return nullptr;
1838 return type;
1839 });
1840 return type ? ParseSuccess : ParseFailure;
1841 });
1842}
1843
Chris Lattner48af7d12018-07-09 19:05:38 -07001844ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001845 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001846 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1847 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001848
1849 // Make sure we have at least one block.
1850 if (getToken().is(Token::r_brace))
1851 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001852
1853 // Parse the list of blocks.
1854 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001855 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001856 return ParseFailure;
1857
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001858 // Verify that all referenced blocks were defined. Iteration over a
1859 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001860 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001861 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001862 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001863 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001864 "reference to an undefined basic block '" + elt.first() +
1865 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001866 }
1867
Chris Lattnera8e47672018-07-25 14:08:16 -07001868 getModule()->getFunctions().push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001869
Chris Lattner40746442018-07-21 14:32:09 -07001870 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001871}
1872
1873/// Basic block declaration.
1874///
1875/// basic-block ::= bb-label instruction* terminator-stmt
1876/// bb-label ::= bb-id bb-arg-list? `:`
1877/// bb-id ::= bare-id
1878/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1879///
Chris Lattner48af7d12018-07-09 19:05:38 -07001880ParseResult CFGFunctionParser::parseBasicBlock() {
1881 SMLoc nameLoc = getToken().getLoc();
1882 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001883 if (parseToken(Token::bare_identifier, "expected basic block name"))
1884 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001885
Chris Lattner48af7d12018-07-09 19:05:38 -07001886 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001887
1888 // If this block has already been parsed, then this is a redefinition with the
1889 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001890 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001891 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1892
Chris Lattner78276e32018-07-07 15:48:26 -07001893 // If an argument list is present, parse it.
1894 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001895 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001896 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1897 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001898 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001899 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001900
James Molloy61a656c2018-07-22 15:45:24 -07001901 // Add the block to the function.
1902 function->push_back(block);
1903
Chris Lattnerf7702a62018-07-23 17:30:01 -07001904 if (parseToken(Token::colon, "expected ':' after basic block name"))
1905 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001906
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001907 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001908 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001909
Chris Lattner7f9cc272018-07-19 08:35:28 -07001910 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1911 ArrayRef<Type *> resultTypes,
1912 ArrayRef<NamedAttribute> attrs) -> Operation * {
1913 SmallVector<CFGValue *, 8> cfgOperands;
1914 cfgOperands.reserve(operands.size());
1915 for (auto *op : operands)
1916 cfgOperands.push_back(cast<CFGValue>(op));
1917 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001918 };
1919
Chris Lattnered65a732018-06-28 20:45:33 -07001920 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001921 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001922 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001923 return ParseFailure;
1924 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001925
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001926 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001927 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001928
1929 return ParseSuccess;
1930}
1931
James Molloy4f788372018-07-24 15:01:27 -07001932ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
1933 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
1934 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1935 if (parseToken(Token::bare_identifier, "expected basic block name"))
1936 return ParseFailure;
1937
1938 if (!consumeIf(Token::l_paren))
1939 return ParseSuccess;
1940 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
1941 parseToken(Token::r_paren, "expected ')' to close argument list"))
1942 return ParseFailure;
1943 return ParseSuccess;
1944}
1945
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001946/// Parse the terminator instruction for a basic block.
1947///
1948/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07001949/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001950/// terminator-stmt ::=
1951/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1952/// terminator-stmt ::= `return` ssa-use-and-type-list?
1953///
Chris Lattner48af7d12018-07-09 19:05:38 -07001954TerminatorInst *CFGFunctionParser::parseTerminator() {
1955 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001956 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001957 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001958
Chris Lattner40746442018-07-21 14:32:09 -07001959 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001960 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07001961
Chris Lattner2c402672018-07-23 11:56:17 -07001962 // Parse any operands.
1963 SmallVector<CFGValue *, 8> operands;
1964 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
1965 return nullptr;
1966 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07001967 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001968
1969 case Token::kw_br: {
1970 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07001971 BasicBlock *destBB;
1972 SmallVector<CFGValue *, 4> values;
1973 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07001974 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07001975 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07001976 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07001977 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001978 }
James Molloy4f788372018-07-24 15:01:27 -07001979
1980 case Token::kw_cond_br: {
1981 consumeToken(Token::kw_cond_br);
1982 SSAUseInfo ssaUse;
1983 if (parseSSAUse(ssaUse))
1984 return nullptr;
1985 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
1986 if (!cond)
1987 return (emitError("expected type was boolean (i1)"), nullptr);
1988 if (parseToken(Token::comma, "expected ',' in conditional branch"))
1989 return nullptr;
1990
1991 BasicBlock *trueBlock;
1992 SmallVector<CFGValue *, 4> trueOperands;
1993 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
1994 return nullptr;
1995
1996 if (parseToken(Token::comma, "expected ',' in conditional branch"))
1997 return nullptr;
1998
1999 BasicBlock *falseBlock;
2000 SmallVector<CFGValue *, 4> falseOperands;
2001 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2002 return nullptr;
2003
2004 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2005 falseBlock);
2006 branch->addTrueOperands(trueOperands);
2007 branch->addFalseOperands(falseOperands);
2008 return branch;
2009 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002010 }
2011}
2012
Chris Lattner48af7d12018-07-09 19:05:38 -07002013//===----------------------------------------------------------------------===//
2014// ML Functions
2015//===----------------------------------------------------------------------===//
2016
2017namespace {
2018/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002019class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002020public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002021 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002022 : FunctionParser(state, Kind::MLFunc), function(function),
2023 builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002024
2025 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002026
2027private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002028 MLFunction *function;
2029
2030 /// This builder intentionally shadows the builder in the base class, with a
2031 /// more specific builder type.
2032 MLFuncBuilder builder;
2033
2034 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002035 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002036 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002037 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002038 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002039 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002040};
2041} // end anonymous namespace
2042
Chris Lattner48af7d12018-07-09 19:05:38 -07002043ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002044 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002045 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002046
Chris Lattnerf7702a62018-07-23 17:30:01 -07002047 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2048 parseStatements(function)) {
2049 return ParseFailure;
2050 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002051
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002052 // TODO: store return operands in the IR.
2053 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002054
Chris Lattnerf7702a62018-07-23 17:30:01 -07002055 if (parseToken(Token::kw_return,
2056 "ML function must end with return statement") ||
2057 parseOptionalSSAUseList(dummyUseInfo) ||
2058 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2059 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002060
Chris Lattnera8e47672018-07-25 14:08:16 -07002061 getModule()->getFunctions().push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002062
Chris Lattner40746442018-07-21 14:32:09 -07002063 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002064}
2065
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002066/// For statement.
2067///
Chris Lattner48af7d12018-07-09 19:05:38 -07002068/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2069/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002070///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002071ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002072 consumeToken(Token::kw_for);
2073
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002074 // Parse induction variable
2075 if (getToken().isNot(Token::percent_identifier))
2076 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002077
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002078 // TODO: create SSA value definition from name
2079 StringRef name = getTokenSpelling().drop_front();
2080 (void)name;
2081
2082 consumeToken(Token::percent_identifier);
2083
Chris Lattnerf7702a62018-07-23 17:30:01 -07002084 if (parseToken(Token::equal, "expected ="))
2085 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002086
2087 // Parse loop bounds
2088 AffineConstantExpr *lowerBound = parseIntConstant();
2089 if (!lowerBound)
2090 return ParseFailure;
2091
Chris Lattnerf7702a62018-07-23 17:30:01 -07002092 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2093 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002094
2095 AffineConstantExpr *upperBound = parseIntConstant();
2096 if (!upperBound)
2097 return ParseFailure;
2098
2099 // Parse step
2100 AffineConstantExpr *step = nullptr;
2101 if (consumeIf(Token::kw_step)) {
2102 step = parseIntConstant();
2103 if (!step)
2104 return ParseFailure;
2105 }
2106
2107 // Create for statement.
2108 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
2109
2110 // If parsing of the for statement body fails,
2111 // MLIR contains for statement with those nested statements that have been
2112 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002113 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
2114 return ParseFailure;
2115
2116 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002117}
2118
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002119// This method is temporary workaround to parse simple loop bounds and
2120// step.
2121// TODO: remove this method once it's no longer used.
2122AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2123 if (getToken().isNot(Token::integer))
2124 return (emitError("expected non-negative integer for now"), nullptr);
2125
2126 auto val = getToken().getUInt64IntegerValue();
2127 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2128 return (emitError("constant too large for affineint"), nullptr);
2129 }
2130 consumeToken(Token::integer);
2131 return builder.getConstantExpr((int64_t)val.getValue());
2132}
2133
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002134/// If statement.
2135///
Chris Lattner48af7d12018-07-09 19:05:38 -07002136/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2137/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2138/// ml-if-stmt ::= ml-if-head
2139/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002140///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002141ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002142 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002143 if (parseToken(Token::l_paren, "expected ("))
2144 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002145
James Molloy0ff71542018-07-23 16:56:32 -07002146 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002147
Chris Lattnerf7702a62018-07-23 17:30:01 -07002148 if (parseToken(Token::r_paren, "expected )"))
2149 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002150
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002151 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002152 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002153
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002154 // When parsing of an if statement body fails, the IR contains
2155 // the if statement with the portion of the body that has been
2156 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002157 if (parseStmtBlock(thenClause))
2158 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002159
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002160 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002161 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002162 if (parseElseClause(elseClause))
2163 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002164 }
2165
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002166 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002167}
2168
2169ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2170 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002171 builder.setInsertionPoint(elseClause);
2172 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002173 }
2174
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002175 return parseStmtBlock(elseClause);
2176}
2177
2178///
2179/// Parse a list of statements ending with `return` or `}`
2180///
2181ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07002182 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
2183 ArrayRef<Type *> resultTypes,
2184 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002185 SmallVector<MLValue *, 8> stmtOperands;
2186 stmtOperands.reserve(operands.size());
2187 for (auto *op : operands)
2188 stmtOperands.push_back(cast<MLValue>(op));
2189 return builder.createOperation(name, stmtOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002190 };
2191
2192 builder.setInsertionPoint(block);
2193
2194 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2195 switch (getToken().getKind()) {
2196 default:
2197 if (parseOperation(createOpFunc))
2198 return ParseFailure;
2199 break;
2200 case Token::kw_for:
2201 if (parseForStmt())
2202 return ParseFailure;
2203 break;
2204 case Token::kw_if:
2205 if (parseIfStmt())
2206 return ParseFailure;
2207 break;
2208 } // end switch
2209 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002210
2211 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002212}
2213
2214///
2215/// Parse `{` ml-stmt* `}`
2216///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002217ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002218 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2219 parseStatements(block) ||
2220 parseToken(Token::r_brace,
2221 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002222 return ParseFailure;
2223
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002224 return ParseSuccess;
2225}
2226
Chris Lattner4c95a502018-06-23 16:03:42 -07002227//===----------------------------------------------------------------------===//
2228// Top-level entity parsing.
2229//===----------------------------------------------------------------------===//
2230
Chris Lattner2e595eb2018-07-10 10:08:27 -07002231namespace {
2232/// This parser handles entities that are only valid at the top level of the
2233/// file.
2234class ModuleParser : public Parser {
2235public:
2236 explicit ModuleParser(ParserState &state) : Parser(state) {}
2237
2238 ParseResult parseModule();
2239
2240private:
2241 ParseResult parseAffineMapDef();
2242
2243 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002244 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2245 SmallVectorImpl<StringRef> &argNames);
2246 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2247 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002248 ParseResult parseExtFunc();
2249 ParseResult parseCFGFunc();
2250 ParseResult parseMLFunc();
2251};
2252} // end anonymous namespace
2253
2254/// Affine map declaration.
2255///
2256/// affine-map-def ::= affine-map-id `=` affine-map-inline
2257///
2258ParseResult ModuleParser::parseAffineMapDef() {
2259 assert(getToken().is(Token::hash_identifier));
2260
2261 StringRef affineMapId = getTokenSpelling().drop_front();
2262
2263 // Check for redefinitions.
2264 auto *&entry = getState().affineMapDefinitions[affineMapId];
2265 if (entry)
2266 return emitError("redefinition of affine map id '" + affineMapId + "'");
2267
2268 consumeToken(Token::hash_identifier);
2269
2270 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002271 if (parseToken(Token::equal,
2272 "expected '=' in affine map outlined definition"))
2273 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002274
2275 entry = parseAffineMapInline();
2276 if (!entry)
2277 return ParseFailure;
2278
Chris Lattner2e595eb2018-07-10 10:08:27 -07002279 return ParseSuccess;
2280}
2281
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002282/// Parse a (possibly empty) list of MLFunction arguments with types.
2283///
2284/// ml-argument ::= ssa-id `:` type
2285/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2286///
2287ParseResult
2288ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2289 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002290 consumeToken(Token::l_paren);
2291
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002292 auto parseElt = [&]() -> ParseResult {
2293 // Parse argument name
2294 if (getToken().isNot(Token::percent_identifier))
2295 return emitError("expected SSA identifier");
2296
2297 StringRef name = getTokenSpelling().drop_front();
2298 consumeToken(Token::percent_identifier);
2299 argNames.push_back(name);
2300
Chris Lattnerf7702a62018-07-23 17:30:01 -07002301 if (parseToken(Token::colon, "expected ':'"))
2302 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002303
2304 // Parse argument type
2305 auto elt = parseType();
2306 if (!elt)
2307 return ParseFailure;
2308 argTypes.push_back(elt);
2309
2310 return ParseSuccess;
2311 };
2312
Chris Lattner40746442018-07-21 14:32:09 -07002313 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002314}
2315
Chris Lattner2e595eb2018-07-10 10:08:27 -07002316/// Parse a function signature, starting with a name and including the parameter
2317/// list.
2318///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002319/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002320/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2321///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002322ParseResult
2323ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2324 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002325 if (getToken().isNot(Token::at_identifier))
2326 return emitError("expected a function identifier like '@foo'");
2327
2328 name = getTokenSpelling().drop_front();
2329 consumeToken(Token::at_identifier);
2330
2331 if (getToken().isNot(Token::l_paren))
2332 return emitError("expected '(' in function signature");
2333
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002334 SmallVector<Type *, 4> argTypes;
2335 ParseResult parseResult;
2336
2337 if (argNames)
2338 parseResult = parseMLArgumentList(argTypes, *argNames);
2339 else
2340 parseResult = parseTypeList(argTypes);
2341
2342 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002343 return ParseFailure;
2344
2345 // Parse the return type if present.
2346 SmallVector<Type *, 4> results;
2347 if (consumeIf(Token::arrow)) {
2348 if (parseTypeList(results))
2349 return ParseFailure;
2350 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002351 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002352 return ParseSuccess;
2353}
2354
2355/// External function declarations.
2356///
2357/// ext-func ::= `extfunc` function-signature
2358///
2359ParseResult ModuleParser::parseExtFunc() {
2360 consumeToken(Token::kw_extfunc);
2361
2362 StringRef name;
2363 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002364 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002365 return ParseFailure;
2366
2367 // Okay, the external function definition was parsed correctly.
Chris Lattnera8e47672018-07-25 14:08:16 -07002368 getModule()->getFunctions().push_back(new ExtFunction(name, type));
Chris Lattner2e595eb2018-07-10 10:08:27 -07002369 return ParseSuccess;
2370}
2371
2372/// CFG function declarations.
2373///
2374/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2375///
2376ParseResult ModuleParser::parseCFGFunc() {
2377 consumeToken(Token::kw_cfgfunc);
2378
2379 StringRef name;
2380 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002381 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002382 return ParseFailure;
2383
2384 // Okay, the CFG function signature was parsed correctly, create the function.
2385 auto function = new CFGFunction(name, type);
2386
2387 return CFGFunctionParser(getState(), function).parseFunctionBody();
2388}
2389
2390/// ML function declarations.
2391///
2392/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2393///
2394ParseResult ModuleParser::parseMLFunc() {
2395 consumeToken(Token::kw_mlfunc);
2396
2397 StringRef name;
2398 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002399 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002400 // FIXME: Parse ML function signature (args + types)
2401 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002402
2403 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002404 return ParseFailure;
2405
2406 // Okay, the ML function signature was parsed correctly, create the function.
2407 auto function = new MLFunction(name, type);
2408
2409 return MLFunctionParser(getState(), function).parseFunctionBody();
2410}
2411
Chris Lattnere79379a2018-06-22 10:39:19 -07002412/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002413ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002414 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002415 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002416 default:
2417 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002418 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002419
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002420 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002421 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002422 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002423
2424 // If we got an error token, then the lexer already emitted an error, just
2425 // stop. Someday we could introduce error recovery if there was demand for
2426 // it.
2427 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002428 return ParseFailure;
2429
2430 case Token::hash_identifier:
2431 if (parseAffineMapDef())
2432 return ParseFailure;
2433 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002434
2435 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002436 if (parseExtFunc())
2437 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002438 break;
2439
Chris Lattner4c95a502018-06-23 16:03:42 -07002440 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002441 if (parseCFGFunc())
2442 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002443 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002444
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002445 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002446 if (parseMLFunc())
2447 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002448 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002449 }
2450 }
2451}
2452
2453//===----------------------------------------------------------------------===//
2454
Jacques Pienaar7b829702018-07-03 13:24:09 -07002455void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2456 const auto &sourceMgr = *error.getSourceMgr();
2457 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2458}
2459
Chris Lattnere79379a2018-06-22 10:39:19 -07002460/// This parses the file specified by the indicated SourceMgr and returns an
2461/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002462Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002463 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002464 // This is the result module we are parsing into.
2465 std::unique_ptr<Module> module(new Module(context));
2466
2467 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002468 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002469 if (ModuleParser(state).parseModule())
2470 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002471
2472 // Make sure the parse module has no other structural problems detected by the
2473 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002474 module->verify();
2475 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002476}