blob: 174d6ca2e4a701fc93746c82488ce9fcfbf23ebf [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 Lattnerea5c3dc2018-08-21 08:42:19 -070029#include "mlir/IR/MLIRContext.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070030#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070031#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070032#include "mlir/IR/OperationSet.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070033#include "mlir/IR/StmtVisitor.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070034#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070035#include "llvm/ADT/DenseMap.h"
36#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070037using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070038using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070039using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070040
Chris Lattnerf7e22732018-06-22 22:03:48 -070041/// Simple enum to make code read better in cases that would otherwise return a
42/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070043enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070044
Chris Lattner48af7d12018-07-09 19:05:38 -070045namespace {
46class Parser;
47
48/// This class refers to all of the state maintained globally by the parser,
49/// such as the current lexer position etc. The Parser base class provides
50/// methods to access this.
51class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070052public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070053 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070054 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070055 : context(module->getContext()), module(module),
56 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070057 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
58 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070059
60 // A map from affine map identifier to AffineMap.
61 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070062
Uday Bondhugulabc535622018-08-07 14:24:38 -070063 // A map from integer set identifier to IntegerSet.
64 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070065
Chris Lattner4613d9e2018-08-19 21:17:22 -070066 // This keeps track of all forward references to functions along with the
67 // temporary function used to represent them and the location of the first
68 // reference.
69 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
70
Chris Lattnere79379a2018-06-22 10:39:19 -070071private:
Chris Lattner48af7d12018-07-09 19:05:38 -070072 ParserState(const ParserState &) = delete;
73 void operator=(const ParserState &) = delete;
74
75 friend class Parser;
76
77 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070078 MLIRContext *const context;
79
80 // This is the module we are parsing into.
81 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070082
83 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070084 Lexer lex;
85
86 // This is the next token that hasn't been consumed yet.
87 Token curToken;
88
Jacques Pienaar9c411be2018-06-24 19:17:35 -070089 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070090 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -070091
92 // The active OperationSet we're parsing with.
93 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070094};
95} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070096
Chris Lattner48af7d12018-07-09 19:05:38 -070097namespace {
98
Chris Lattner992a1272018-08-07 12:02:37 -070099typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700100 CreateOperationFunction;
101
Chris Lattner48af7d12018-07-09 19:05:38 -0700102/// This class implement support for parsing global entities like types and
103/// shared entities like SSA names. It is intended to be subclassed by
104/// specialized subparsers that include state, e.g. when a local symbol table.
105class Parser {
106public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700107 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700108
Chris Lattner2e595eb2018-07-10 10:08:27 -0700109 Parser(ParserState &state) : builder(state.context), state(state) {}
110
111 // Helper methods to get stuff from the parser-global state.
112 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700113 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700114 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700115 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700116 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700117
118 /// Return the current token the parser is inspecting.
119 const Token &getToken() const { return state.curToken; }
120 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700121
122 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700123 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700124 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700125 }
126 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700127
128 /// Advance the current lexer onto the next token.
129 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700130 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700131 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700132 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700133 }
134
135 /// Advance the current lexer onto the next token, asserting what the expected
136 /// current token is. This is preferred to the above method because it leads
137 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700138 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700139 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700140 consumeToken();
141 }
142
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700143 /// If the current token has the specified kind, consume it and return true.
144 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700145 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700146 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700147 return false;
148 consumeToken(kind);
149 return true;
150 }
151
Chris Lattnerf7702a62018-07-23 17:30:01 -0700152 /// Consume the specified token if present and return success. On failure,
153 /// output a diagnostic and return failure.
154 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
155
Chris Lattner40746442018-07-21 14:32:09 -0700156 /// Parse a comma-separated list of elements up until the specified end token.
157 ParseResult
158 parseCommaSeparatedListUntil(Token::Kind rightToken,
159 const std::function<ParseResult()> &parseElement,
160 bool allowEmptyList = true);
161
162 /// Parse a comma separated list of elements that must have at least one entry
163 /// in it.
164 ParseResult
165 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700166
Chris Lattnerf7e22732018-06-22 22:03:48 -0700167 // We have two forms of parsing methods - those that return a non-null
168 // pointer on success, and those that return a ParseResult to indicate whether
169 // they returned a failure. The second class fills in by-reference arguments
170 // as the results of their action.
171
Chris Lattnere79379a2018-06-22 10:39:19 -0700172 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700173 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700174 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700175 Type *parseTensorType();
176 Type *parseMemRefType();
177 Type *parseFunctionType();
178 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700179 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700180 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700181
Chris Lattner7121b802018-07-04 20:45:39 -0700182 // Attribute parsing.
183 Attribute *parseAttribute();
184 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
185
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700186 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700187 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700188 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700189 IntegerSet *parseIntegerSetInline();
190 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700191
Chris Lattner48af7d12018-07-09 19:05:38 -0700192private:
193 // The Parser is subclassed and reinstantiated. Do not add additional
194 // non-trivial state here, add it to the ParserState class.
195 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700196};
197} // end anonymous namespace
198
199//===----------------------------------------------------------------------===//
200// Helper methods.
201//===----------------------------------------------------------------------===//
202
Chris Lattner4c95a502018-06-23 16:03:42 -0700203ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700204 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700205 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700206 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700207 return ParseFailure;
208
Chris Lattner48af7d12018-07-09 19:05:38 -0700209 auto &sourceMgr = state.lex.getSourceMgr();
210 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700211 return ParseFailure;
212}
213
Chris Lattnerf7702a62018-07-23 17:30:01 -0700214/// Consume the specified token if present and return success. On failure,
215/// output a diagnostic and return failure.
216ParseResult Parser::parseToken(Token::Kind expectedToken,
217 const Twine &message) {
218 if (consumeIf(expectedToken))
219 return ParseSuccess;
220 return emitError(message);
221}
222
Chris Lattner40746442018-07-21 14:32:09 -0700223/// Parse a comma separated list of elements that must have at least one entry
224/// in it.
225ParseResult Parser::parseCommaSeparatedList(
226 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700227 // Non-empty case starts with an element.
228 if (parseElement())
229 return ParseFailure;
230
231 // Otherwise we have a list of comma separated elements.
232 while (consumeIf(Token::comma)) {
233 if (parseElement())
234 return ParseFailure;
235 }
Chris Lattner40746442018-07-21 14:32:09 -0700236 return ParseSuccess;
237}
238
239/// Parse a comma-separated list of elements, terminated with an arbitrary
240/// token. This allows empty lists if allowEmptyList is true.
241///
242/// abstract-list ::= rightToken // if allowEmptyList == true
243/// abstract-list ::= element (',' element)* rightToken
244///
245ParseResult Parser::parseCommaSeparatedListUntil(
246 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
247 bool allowEmptyList) {
248 // Handle the empty case.
249 if (getToken().is(rightToken)) {
250 if (!allowEmptyList)
251 return emitError("expected list element");
252 consumeToken(rightToken);
253 return ParseSuccess;
254 }
255
Chris Lattnerf7702a62018-07-23 17:30:01 -0700256 if (parseCommaSeparatedList(parseElement) ||
257 parseToken(rightToken, "expected ',' or '" +
258 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700259 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700260
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700261 return ParseSuccess;
262}
Chris Lattnere79379a2018-06-22 10:39:19 -0700263
264//===----------------------------------------------------------------------===//
265// Type Parsing
266//===----------------------------------------------------------------------===//
267
Chris Lattnerc3251192018-07-27 13:09:58 -0700268/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269///
Chris Lattnerc3251192018-07-27 13:09:58 -0700270/// type ::= integer-type
271/// | float-type
272/// | other-type
273/// | vector-type
274/// | tensor-type
275/// | memref-type
276/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700277///
Chris Lattnerc3251192018-07-27 13:09:58 -0700278/// float-type ::= `f16` | `bf16` | `f32` | `f64`
279/// other-type ::= `affineint` | `tf_control`
280///
281Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700282 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700283 default:
284 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700285 case Token::kw_memref:
286 return parseMemRefType();
287 case Token::kw_tensor:
288 return parseTensorType();
289 case Token::kw_vector:
290 return parseVectorType();
291 case Token::l_paren:
292 return parseFunctionType();
293 // integer-type
294 case Token::inttype: {
295 auto width = getToken().getIntTypeBitwidth();
296 if (!width.hasValue())
297 return (emitError("invalid integer width"), nullptr);
298 consumeToken(Token::inttype);
299 return builder.getIntegerType(width.getValue());
300 }
301
302 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700303 case Token::kw_bf16:
304 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700305 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700306 case Token::kw_f16:
307 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700308 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700309 case Token::kw_f32:
310 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700311 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700312 case Token::kw_f64:
313 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700314 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700315
316 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700317 case Token::kw_affineint:
318 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700319 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700320 case Token::kw_tf_control:
321 consumeToken(Token::kw_tf_control);
322 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700323 case Token::kw_tf_string:
324 consumeToken(Token::kw_tf_string);
325 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700326 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700327}
328
329/// Parse a vector type.
330///
331/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
332/// const-dimension-list ::= (integer-literal `x`)+
333///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700334VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700335 consumeToken(Token::kw_vector);
336
Chris Lattnerf7702a62018-07-23 17:30:01 -0700337 if (parseToken(Token::less, "expected '<' in vector type"))
338 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700339
Chris Lattner48af7d12018-07-09 19:05:38 -0700340 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700341 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700342
343 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700344 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700345 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700346 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700348 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700349 dimensions.push_back(dimension.getValue());
350
351 consumeToken(Token::integer);
352
353 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700354 if (getToken().isNot(Token::bare_identifier) ||
355 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700356 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700357
358 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700359 if (getTokenSpelling().size() != 1)
360 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700361
362 // Consume the 'x'.
363 consumeToken(Token::bare_identifier);
364 }
365
366 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700367 auto typeLoc = getToken().getLoc();
368 auto *elementType = parseType();
369 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700370 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700371
Chris Lattnerc3251192018-07-27 13:09:58 -0700372 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
373 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700374
Chris Lattnerf7e22732018-06-22 22:03:48 -0700375 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700376}
377
378/// Parse a dimension list of a tensor or memref type. This populates the
379/// dimension list, returning -1 for the '?' dimensions.
380///
381/// dimension-list-ranked ::= (dimension `x`)*
382/// dimension ::= `?` | integer-literal
383///
384ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700385 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700386 if (consumeIf(Token::question)) {
387 dimensions.push_back(-1);
388 } else {
389 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700390 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700391 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
392 return emitError("invalid dimension");
393 dimensions.push_back((int)dimension.getValue());
394 consumeToken(Token::integer);
395 }
396
397 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700398 if (getToken().isNot(Token::bare_identifier) ||
399 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700400 return emitError("expected 'x' in dimension list");
401
402 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700403 if (getTokenSpelling().size() != 1)
404 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700405
406 // Consume the 'x'.
407 consumeToken(Token::bare_identifier);
408 }
409
410 return ParseSuccess;
411}
412
413/// Parse a tensor type.
414///
415/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
416/// dimension-list ::= dimension-list-ranked | `??`
417///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700418Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700419 consumeToken(Token::kw_tensor);
420
Chris Lattnerf7702a62018-07-23 17:30:01 -0700421 if (parseToken(Token::less, "expected '<' in tensor type"))
422 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700423
424 bool isUnranked;
425 SmallVector<int, 4> dimensions;
426
427 if (consumeIf(Token::questionquestion)) {
428 isUnranked = true;
429 } else {
430 isUnranked = false;
431 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700432 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433 }
434
435 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700436 auto typeLoc = getToken().getLoc();
437 auto *elementType = parseType();
438 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700439 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700440
Chris Lattnerc3251192018-07-27 13:09:58 -0700441 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
442 !isa<VectorType>(elementType))
443 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700444
MLIR Team355ec862018-06-23 18:09:09 -0700445 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700446 return builder.getTensorType(elementType);
447 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700448}
449
450/// Parse a memref type.
451///
452/// memref-type ::= `memref` `<` dimension-list-ranked element-type
453/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
454///
455/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
456/// memory-space ::= integer-literal /* | TODO: address-space-id */
457///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700458Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700459 consumeToken(Token::kw_memref);
460
Chris Lattnerf7702a62018-07-23 17:30:01 -0700461 if (parseToken(Token::less, "expected '<' in memref type"))
462 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700463
464 SmallVector<int, 4> dimensions;
465 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700466 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700467
468 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700469 auto typeLoc = getToken().getLoc();
470 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700471 if (!elementType)
472 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700473
Chris Lattnerc3251192018-07-27 13:09:58 -0700474 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
475 !isa<VectorType>(elementType))
476 return (emitError(typeLoc, "invalid memref element type"), nullptr);
477
MLIR Team718c82f2018-07-16 09:45:22 -0700478 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700479 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700480 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700481 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482
MLIR Team718c82f2018-07-16 09:45:22 -0700483 auto parseElt = [&]() -> ParseResult {
484 if (getToken().is(Token::integer)) {
485 // Parse memory space.
486 if (parsedMemorySpace)
487 return emitError("multiple memory spaces specified in memref type");
488 auto v = getToken().getUnsignedIntegerValue();
489 if (!v.hasValue())
490 return emitError("invalid memory space in memref type");
491 memorySpace = v.getValue();
492 consumeToken(Token::integer);
493 parsedMemorySpace = true;
494 } else {
495 // Parse affine map.
496 if (parsedMemorySpace)
497 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700498 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700499 if (affineMap == nullptr)
500 return ParseFailure;
501 affineMapComposition.push_back(affineMap);
502 }
503 return ParseSuccess;
504 };
505
Chris Lattner413db6a2018-07-25 12:55:50 -0700506 // Parse a list of mappings and address space if present.
507 if (consumeIf(Token::comma)) {
508 // Parse comma separated list of affine maps, followed by memory space.
509 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
510 /*allowEmptyList=*/false)) {
511 return nullptr;
512 }
513 } else {
514 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
515 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700516 }
MLIR Team718c82f2018-07-16 09:45:22 -0700517
518 return MemRefType::get(dimensions, elementType, affineMapComposition,
519 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700520}
521
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700522/// Parse a function type.
523///
524/// function-type ::= type-list-parens `->` type-list
525///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700526Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700527 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700528
Chris Lattnerf7702a62018-07-23 17:30:01 -0700529 SmallVector<Type *, 4> arguments, results;
530 if (parseTypeList(arguments) ||
531 parseToken(Token::arrow, "expected '->' in function type") ||
532 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700533 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700534
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700535 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700536}
537
Chris Lattner1604e472018-07-23 08:42:19 -0700538/// Parse a list of types without an enclosing parenthesis. The list must have
539/// at least one member.
540///
541/// type-list-no-parens ::= type (`,` type)*
542///
543ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
544 auto parseElt = [&]() -> ParseResult {
545 auto elt = parseType();
546 elements.push_back(elt);
547 return elt ? ParseSuccess : ParseFailure;
548 };
549
550 return parseCommaSeparatedList(parseElt);
551}
552
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700553/// Parse a "type list", which is a singular type, or a parenthesized list of
554/// types.
555///
556/// type-list ::= type-list-parens | type
557/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700558/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700559///
James Molloy0ff71542018-07-23 16:56:32 -0700560ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700561 auto parseElt = [&]() -> ParseResult {
562 auto elt = parseType();
563 elements.push_back(elt);
564 return elt ? ParseSuccess : ParseFailure;
565 };
566
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700567 // If there is no parens, then it must be a singular type.
568 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700569 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700570
Chris Lattner40746442018-07-21 14:32:09 -0700571 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700572 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700573
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700574 return ParseSuccess;
575}
576
Chris Lattner4c95a502018-06-23 16:03:42 -0700577//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700578// Attribute parsing.
579//===----------------------------------------------------------------------===//
580
Chris Lattner7121b802018-07-04 20:45:39 -0700581/// Attribute parsing.
582///
583/// attribute-value ::= bool-literal
584/// | integer-literal
585/// | float-literal
586/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700587/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700588/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700589/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700590///
591Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700592 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700593 case Token::kw_true:
594 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700595 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700596 case Token::kw_false:
597 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700598 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700599
Jacques Pienaar84491092018-07-31 17:15:15 -0700600 case Token::floatliteral: {
601 auto val = getToken().getFloatingPointValue();
602 if (!val.hasValue())
603 return (emitError("floating point value too large for attribute"),
604 nullptr);
605 consumeToken(Token::floatliteral);
606 return builder.getFloatAttr(val.getValue());
607 }
Chris Lattner7121b802018-07-04 20:45:39 -0700608 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700609 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700610 if (!val.hasValue() || (int64_t)val.getValue() < 0)
611 return (emitError("integer too large for attribute"), nullptr);
612 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700613 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700614 }
615
616 case Token::minus: {
617 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700618 if (getToken().is(Token::integer)) {
619 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700620 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
621 return (emitError("integer too large for attribute"), nullptr);
622 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700623 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700624 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700625 if (getToken().is(Token::floatliteral)) {
626 auto val = getToken().getFloatingPointValue();
627 if (!val.hasValue())
628 return (emitError("floating point value too large for attribute"),
629 nullptr);
630 consumeToken(Token::floatliteral);
631 return builder.getFloatAttr(-val.getValue());
632 }
Chris Lattner7121b802018-07-04 20:45:39 -0700633
634 return (emitError("expected constant integer or floating point value"),
635 nullptr);
636 }
637
638 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700639 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700640 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700641 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700642 }
643
Chris Lattner85ee1512018-07-25 11:15:20 -0700644 case Token::l_square: {
645 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700646 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700647
648 auto parseElt = [&]() -> ParseResult {
649 elements.push_back(parseAttribute());
650 return elements.back() ? ParseSuccess : ParseFailure;
651 };
652
Chris Lattner85ee1512018-07-25 11:15:20 -0700653 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700654 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700655 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700656 }
James Molloyf0d2f442018-08-03 01:54:46 -0700657 case Token::hash_identifier:
658 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700659 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700660 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700661 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700662 return (emitError("expected constant attribute value"), nullptr);
663 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700664
665 case Token::at_identifier: {
666 auto nameLoc = getToken().getLoc();
667 Identifier name = builder.getIdentifier(getTokenSpelling().drop_front());
668 consumeToken(Token::at_identifier);
669
670 if (parseToken(Token::colon, "expected ':' and function type"))
671 return nullptr;
672 auto typeLoc = getToken().getLoc();
673 Type *type = parseType();
674 if (!type)
675 return nullptr;
676 auto fnType = dyn_cast<FunctionType>(type);
677 if (!fnType)
678 return (emitError(typeLoc, "expected function type"), nullptr);
679
680 // See if the function has already been defined in the module.
681 Function *function = getModule()->getNamedFunction(name);
682
683 // If not, get or create a forward reference to one.
684 if (!function) {
685 auto &entry = state.functionForwardRefs[name];
686 if (!entry.first) {
687 entry.first = new ExtFunction(name, fnType);
688 entry.second = nameLoc;
689 }
690 function = entry.first;
691 }
692
693 if (function->getType() != type)
694 return (emitError(typeLoc, "reference to function with mismatched type"),
695 nullptr);
696
697 return builder.getFunctionAttr(function);
698 }
699
James Molloyf0d2f442018-08-03 01:54:46 -0700700 default: {
701 if (Type *type = parseType())
702 return builder.getTypeAttr(type);
703 return nullptr;
704 }
705 }
Chris Lattner7121b802018-07-04 20:45:39 -0700706}
707
Chris Lattner7121b802018-07-04 20:45:39 -0700708/// Attribute dictionary.
709///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700710/// attribute-dict ::= `{` `}`
711/// | `{` attribute-entry (`,` attribute-entry)* `}`
712/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700713///
James Molloy0ff71542018-07-23 16:56:32 -0700714ParseResult
715Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700716 consumeToken(Token::l_brace);
717
718 auto parseElt = [&]() -> ParseResult {
719 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700720 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
721 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700722 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700723 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700724 consumeToken();
725
Chris Lattnerf7702a62018-07-23 17:30:01 -0700726 if (parseToken(Token::colon, "expected ':' in attribute list"))
727 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700728
729 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700730 if (!attr)
731 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700732
733 attributes.push_back({nameId, attr});
734 return ParseSuccess;
735 };
736
Chris Lattner40746442018-07-21 14:32:09 -0700737 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700738 return ParseFailure;
739
740 return ParseSuccess;
741}
742
743//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700744// Polyhedral structures.
745//===----------------------------------------------------------------------===//
746
Chris Lattner2e595eb2018-07-10 10:08:27 -0700747/// Lower precedence ops (all at the same precedence level). LNoOp is false in
748/// the boolean sense.
749enum AffineLowPrecOp {
750 /// Null value.
751 LNoOp,
752 Add,
753 Sub
754};
MLIR Teamf85a6262018-06-27 11:03:08 -0700755
Chris Lattner2e595eb2018-07-10 10:08:27 -0700756/// Higher precedence ops - all at the same precedence level. HNoOp is false in
757/// the boolean sense.
758enum AffineHighPrecOp {
759 /// Null value.
760 HNoOp,
761 Mul,
762 FloorDiv,
763 CeilDiv,
764 Mod
765};
Chris Lattner7121b802018-07-04 20:45:39 -0700766
Chris Lattner2e595eb2018-07-10 10:08:27 -0700767namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700768/// This is a specialized parser for affine structures (affine maps, affine
769/// expressions, and integer sets), maintaining the state transient to their
770/// bodies.
771class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700772public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700773 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700774
Chris Lattner2e595eb2018-07-10 10:08:27 -0700775 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700776 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700777
Chris Lattner2e595eb2018-07-10 10:08:27 -0700778private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700779 // Binary affine op parsing.
780 AffineLowPrecOp consumeIfLowPrecOp();
781 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700782
Chris Lattner2e595eb2018-07-10 10:08:27 -0700783 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700784 ParseResult parseDimIdList(unsigned &numDims);
785 ParseResult parseSymbolIdList(unsigned &numSymbols);
786 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700787
788 AffineExpr *parseAffineExpr();
789 AffineExpr *parseParentheticalExpr();
790 AffineExpr *parseNegateExpression(AffineExpr *lhs);
791 AffineExpr *parseIntegerExpr();
792 AffineExpr *parseBareIdExpr();
793
794 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700795 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700796 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
797 AffineExpr *rhs);
798 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
799 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
800 AffineLowPrecOp llhsOp);
801 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700802 AffineHighPrecOp llhsOp,
803 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700804 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700805
806private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700807 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700808};
809} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700810
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700811/// Create an affine binary high precedence op expression (mul's, div's, mod).
812/// opLoc is the location of the op token to be used to report errors
813/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700814AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
815 AffineExpr *lhs,
816 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700817 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700818 switch (op) {
819 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700820 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700821 emitError(opLoc, "non-affine expression: at least one of the multiply "
822 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700823 return nullptr;
824 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700825 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700826 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700827 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700828 emitError(opLoc, "non-affine expression: right operand of floordiv "
829 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700830 return nullptr;
831 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700832 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700833 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700834 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700835 emitError(opLoc, "non-affine expression: right operand of ceildiv "
836 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700837 return nullptr;
838 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700839 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700840 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700841 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700842 emitError(opLoc, "non-affine expression: right operand of mod "
843 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700844 return nullptr;
845 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700846 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700847 case HNoOp:
848 llvm_unreachable("can't create affine expression for null high prec op");
849 return nullptr;
850 }
851}
852
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700854AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
855 AffineExpr *lhs,
856 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700857 switch (op) {
858 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700859 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700860 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700861 return builder.getAddExpr(
862 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700863 case AffineLowPrecOp::LNoOp:
864 llvm_unreachable("can't create affine expression for null low prec op");
865 return nullptr;
866 }
867}
868
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700869/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700870/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700871AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700872 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700873 case Token::plus:
874 consumeToken(Token::plus);
875 return AffineLowPrecOp::Add;
876 case Token::minus:
877 consumeToken(Token::minus);
878 return AffineLowPrecOp::Sub;
879 default:
880 return AffineLowPrecOp::LNoOp;
881 }
882}
883
884/// Consume this token if it is a higher precedence affine op (there are only
885/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700886AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700887 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700888 case Token::star:
889 consumeToken(Token::star);
890 return Mul;
891 case Token::kw_floordiv:
892 consumeToken(Token::kw_floordiv);
893 return FloorDiv;
894 case Token::kw_ceildiv:
895 consumeToken(Token::kw_ceildiv);
896 return CeilDiv;
897 case Token::kw_mod:
898 consumeToken(Token::kw_mod);
899 return Mod;
900 default:
901 return HNoOp;
902 }
903}
904
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700905/// Parse a high precedence op expression list: mul, div, and mod are high
906/// precedence binary ops, i.e., parse a
907/// expr_1 op_1 expr_2 op_2 ... expr_n
908/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
909/// All affine binary ops are left associative.
910/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
911/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700912/// null. llhsOpLoc is the location of the llhsOp token that will be used to
913/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700914AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
915 AffineHighPrecOp llhsOp,
916 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700917 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700918 if (!lhs)
919 return nullptr;
920
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700921 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700922 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700923 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700924 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700925 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700926 if (!expr)
927 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700928 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929 }
930 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700931 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700932 }
933
934 // This is the last operand in this expression.
935 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700936 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937
938 // No llhs, 'lhs' itself is the expression.
939 return lhs;
940}
941
942/// Parse an affine expression inside parentheses.
943///
944/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700945AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700946 if (parseToken(Token::l_paren, "expected '('"))
947 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700948 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700949 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700950
Chris Lattner2e595eb2018-07-10 10:08:27 -0700951 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700954 if (parseToken(Token::r_paren, "expected ')'"))
955 return nullptr;
956
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700957 return expr;
958}
959
960/// Parse the negation expression.
961///
962/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700963AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700964 if (parseToken(Token::minus, "expected '-'"))
965 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700966
Chris Lattner2e595eb2018-07-10 10:08:27 -0700967 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700968 // Since negation has the highest precedence of all ops (including high
969 // precedence ops) but lower than parentheses, we are only going to use
970 // parseAffineOperandExpr instead of parseAffineExpr here.
971 if (!operand)
972 // Extra error message although parseAffineOperandExpr would have
973 // complained. Leads to a better diagnostic.
974 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700975 auto *minusOne = builder.getConstantExpr(-1);
976 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977}
978
979/// Parse a bare id that may appear in an affine expression.
980///
981/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -0700982AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700983 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700984 return (emitError("expected bare identifier"), nullptr);
985
Chris Lattner48af7d12018-07-09 19:05:38 -0700986 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700987 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700988 if (entry.first == sRef) {
989 consumeToken(Token::bare_identifier);
990 return entry.second;
991 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700992 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700993
994 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700995}
996
997/// Parse a positive integral constant appearing in an affine expression.
998///
999/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001000AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001001 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001002 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001003 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001004
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001005 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001006 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001007}
1008
1009/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001010/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1011/// operator, the rhs of which is being parsed. This is used to determine
1012/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001013// Eg: for an expression without parentheses (like i + j + k + l), each
1014// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1015// operand expression, it's an op expression and will be parsed via
1016// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1017// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001018AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001019 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001020 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001021 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001022 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001023 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001024 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001025 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001026 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001027 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001028 case Token::kw_ceildiv:
1029 case Token::kw_floordiv:
1030 case Token::kw_mod:
1031 case Token::plus:
1032 case Token::star:
1033 if (lhs)
1034 emitError("missing right operand of binary operator");
1035 else
1036 emitError("missing left operand of binary operator");
1037 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038 default:
1039 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001040 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001041 else
1042 emitError("expected affine expression");
1043 return nullptr;
1044 }
1045}
1046
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047/// Parse affine expressions that are bare-id's, integer constants,
1048/// parenthetical affine expressions, and affine op expressions that are a
1049/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001050///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001051/// All binary op's associate from left to right.
1052///
1053/// {add, sub} have lower precedence than {mul, div, and mod}.
1054///
Uday Bondhugula76345202018-07-09 13:47:52 -07001055/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1056/// ceildiv, and mod are at the same higher precedence level. Negation has
1057/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001058///
1059/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001060/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1061/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1062/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001063/// associativity.
1064///
1065/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001066/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1067/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001068AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1069 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001070 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001071 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001072 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001073
1074 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001075 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001076 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001077 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001078 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001079 }
1080 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001081 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001082 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001083 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001084 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001085 // We have a higher precedence op here. Get the rhs operand for the llhs
1086 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001087 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001088 if (!highRes)
1089 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001090
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001091 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001092 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001093 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001094 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001096 // Recurse for subsequent low prec op's after the affine high prec op
1097 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001098 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1099 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001100 return expr;
1101 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001102 // Last operand in the expression list.
1103 if (llhs)
1104 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1105 // No llhs, 'lhs' itself is the expression.
1106 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001107}
1108
1109/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001110/// affine-expr ::= `(` affine-expr `)`
1111/// | `-` affine-expr
1112/// | affine-expr `+` affine-expr
1113/// | affine-expr `-` affine-expr
1114/// | affine-expr `*` affine-expr
1115/// | affine-expr `floordiv` affine-expr
1116/// | affine-expr `ceildiv` affine-expr
1117/// | affine-expr `mod` affine-expr
1118/// | bare-id
1119/// | integer-literal
1120///
1121/// Additional conditions are checked depending on the production. For eg., one
1122/// of the operands for `*` has to be either constant/symbolic; the second
1123/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001124AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001125 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001126}
1127
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001128/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001129/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001130/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001131ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001132 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001133 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001134
1135 auto name = getTokenSpelling();
1136 for (auto entry : dimsAndSymbols) {
1137 if (entry.first == name)
1138 return emitError("redefinition of identifier '" + Twine(name) + "'");
1139 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001140 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001141
1142 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001143 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001144}
1145
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001146/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001147ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001148 consumeToken(Token::l_square);
1149 auto parseElt = [&]() -> ParseResult {
1150 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1151 return parseIdentifierDefinition(symbol);
1152 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001153 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001154}
1155
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001156/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001157ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001158 if (parseToken(Token::l_paren,
1159 "expected '(' at start of dimensional identifiers list"))
1160 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001161
Chris Lattner413db6a2018-07-25 12:55:50 -07001162 auto parseElt = [&]() -> ParseResult {
1163 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1164 return parseIdentifierDefinition(dimension);
1165 };
Chris Lattner40746442018-07-21 14:32:09 -07001166 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001167}
1168
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001169/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001170///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001171/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1172/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1173/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001174///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001175/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001176AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001177 unsigned numDims = 0, numSymbols = 0;
1178
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001179 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001180 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001181 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001182
1183 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001184 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001185 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001186 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001187 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001188
1189 if (parseToken(Token::arrow, "expected '->' or '['") ||
1190 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001191 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001192
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001193 SmallVector<AffineExpr *, 4> exprs;
1194 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001195 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001196 ParseResult res = elt ? ParseSuccess : ParseFailure;
1197 exprs.push_back(elt);
1198 return res;
1199 };
1200
1201 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001202 // affine expressions); the list cannot be empty.
1203 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001204 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001205 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001206
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001207 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001208 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1209 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1210 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001211 // TODO: check if sizes are non-negative whenever they are constant.
1212 SmallVector<AffineExpr *, 4> rangeSizes;
1213 if (consumeIf(Token::kw_size)) {
1214 // Location of the l_paren token (if it exists) for error reporting later.
1215 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001216 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1217 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001218
1219 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001220 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001221 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001222 if (!elt)
1223 return ParseFailure;
1224
1225 if (!elt->isSymbolicOrConstant())
1226 return emitError(loc,
1227 "size expressions cannot refer to dimension values");
1228
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001229 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001230 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001231 };
1232
Chris Lattner40746442018-07-21 14:32:09 -07001233 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001234 return nullptr;
1235 if (exprs.size() > rangeSizes.size())
1236 return (emitError(loc, "fewer range sizes than range expressions"),
1237 nullptr);
1238 if (exprs.size() < rangeSizes.size())
1239 return (emitError(loc, "more range sizes than range expressions"),
1240 nullptr);
1241 }
1242
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001243 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001244 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001245}
1246
Chris Lattner2e595eb2018-07-10 10:08:27 -07001247AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001248 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001249}
1250
MLIR Team718c82f2018-07-16 09:45:22 -07001251AffineMap *Parser::parseAffineMapReference() {
1252 if (getToken().is(Token::hash_identifier)) {
1253 // Parse affine map identifier and verify that it exists.
1254 StringRef affineMapId = getTokenSpelling().drop_front();
1255 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1256 return (emitError("undefined affine map id '" + affineMapId + "'"),
1257 nullptr);
1258 consumeToken(Token::hash_identifier);
1259 return getState().affineMapDefinitions[affineMapId];
1260 }
1261 // Try to parse inline affine map.
1262 return parseAffineMapInline();
1263}
1264
MLIR Teamf85a6262018-06-27 11:03:08 -07001265//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001266// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001267//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001268
Chris Lattner7f9cc272018-07-19 08:35:28 -07001269namespace {
1270/// This class contains parser state that is common across CFG and ML functions,
1271/// notably for dealing with operations and SSA values.
1272class FunctionParser : public Parser {
1273public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001274 enum class Kind { CFGFunc, MLFunc };
1275
1276 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001277
Chris Lattner6119d382018-07-20 18:41:34 -07001278 /// After the function is finished parsing, this function checks to see if
1279 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001280 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001281
1282 /// This represents a use of an SSA value in the program. The first two
1283 /// entries in the tuple are the name and result number of a reference. The
1284 /// third is the location of the reference, which is used in case this ends up
1285 /// being a use of an undefined value.
1286 struct SSAUseInfo {
1287 StringRef name; // Value name, e.g. %42 or %abc
1288 unsigned number; // Number, specified with #12
1289 SMLoc loc; // Location of first definition or use.
1290 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001291
1292 /// Given a reference to an SSA value and its type, return a reference. This
1293 /// returns null on failure.
1294 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1295
1296 /// Register a definition of a value with the symbol table.
1297 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1298
1299 // SSA parsing productions.
1300 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001301 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001302
1303 template <typename ResultType>
1304 ResultType parseSSADefOrUseAndType(
1305 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1306
1307 SSAValue *parseSSAUseAndType() {
1308 return parseSSADefOrUseAndType<SSAValue *>(
1309 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1310 return resolveSSAUse(useInfo, type);
1311 });
1312 }
Chris Lattner40746442018-07-21 14:32:09 -07001313
1314 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001315 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001316 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1317 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001318
1319 // Operations
1320 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001321 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1322 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001323
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001324protected:
1325 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1326
Chris Lattner7f9cc272018-07-19 08:35:28 -07001327private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001328 /// Kind indicates if this is CFG or ML function parser.
1329 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001330 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001331 /// their name. This has one entry per result number.
1332 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1333
1334 /// These are all of the placeholders we've made along with the location of
1335 /// their first reference, to allow checking for use of undefined values.
1336 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1337
1338 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1339
1340 /// Return true if this is a forward reference.
1341 bool isForwardReferencePlaceholder(SSAValue *value) {
1342 return forwardReferencePlaceholders.count(value);
1343 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001344};
1345} // end anonymous namespace
1346
Chris Lattner6119d382018-07-20 18:41:34 -07001347/// Create and remember a new placeholder for a forward reference.
1348SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1349 Type *type) {
1350 // Forward references are always created as instructions, even in ML
1351 // functions, because we just need something with a def/use chain.
1352 //
1353 // We create these placeholders as having an empty name, which we know cannot
1354 // be created through normal user input, allowing us to distinguish them.
1355 auto name = Identifier::get("placeholder", getContext());
1356 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1357 getContext());
1358 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1359 return inst->getResult(0);
1360}
1361
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001362/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001363/// it specifies. This returns null on failure.
1364SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001365 auto &entries = values[useInfo.name];
1366
Chris Lattner7f9cc272018-07-19 08:35:28 -07001367 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001368 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1369 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001370 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001371 if (result->getType() == type)
1372 return result;
1373
Chris Lattner6119d382018-07-20 18:41:34 -07001374 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1375 "' expects different type than prior uses");
1376 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001377 return nullptr;
1378 }
1379
Chris Lattner6119d382018-07-20 18:41:34 -07001380 // Make sure we have enough slots for this.
1381 if (entries.size() <= useInfo.number)
1382 entries.resize(useInfo.number + 1);
1383
1384 // If the value has already been defined and this is an overly large result
1385 // number, diagnose that.
1386 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1387 return (emitError(useInfo.loc, "reference to invalid result number"),
1388 nullptr);
1389
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001390 // Otherwise, this is a forward reference. If we are in ML function return
1391 // an error. In CFG function, create a placeholder and remember
1392 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001393 if (getKind() == Kind::MLFunc)
1394 return (
1395 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1396 nullptr);
1397
Chris Lattner6119d382018-07-20 18:41:34 -07001398 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1399 entries[useInfo.number].first = result;
1400 entries[useInfo.number].second = useInfo.loc;
1401 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001402}
1403
1404/// Register a definition of a value with the symbol table.
1405ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001406 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001407
Chris Lattner6119d382018-07-20 18:41:34 -07001408 // Make sure there is a slot for this value.
1409 if (entries.size() <= useInfo.number)
1410 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001411
Chris Lattner6119d382018-07-20 18:41:34 -07001412 // If we already have an entry for this, check to see if it was a definition
1413 // or a forward reference.
1414 if (auto *existing = entries[useInfo.number].first) {
1415 if (!isForwardReferencePlaceholder(existing)) {
1416 emitError(useInfo.loc,
1417 "redefinition of SSA value '" + useInfo.name + "'");
1418 return emitError(entries[useInfo.number].second,
1419 "previously defined here");
1420 }
1421
1422 // If it was a forward reference, update everything that used it to use the
1423 // actual definition instead, delete the forward ref, and remove it from our
1424 // set of forward references we track.
1425 existing->replaceAllUsesWith(value);
1426 existing->getDefiningInst()->destroy();
1427 forwardReferencePlaceholders.erase(existing);
1428 }
1429
1430 entries[useInfo.number].first = value;
1431 entries[useInfo.number].second = useInfo.loc;
1432 return ParseSuccess;
1433}
1434
1435/// After the function is finished parsing, this function checks to see if
1436/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001437ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001438 // Check for any forward references that are left. If we find any, error out.
1439 if (!forwardReferencePlaceholders.empty()) {
1440 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1441 // Iteration over the map isn't determinstic, so sort by source location.
1442 for (auto entry : forwardReferencePlaceholders)
1443 errors.push_back({entry.second.getPointer(), entry.first});
1444 llvm::array_pod_sort(errors.begin(), errors.end());
1445
1446 for (auto entry : errors)
1447 emitError(SMLoc::getFromPointer(entry.first),
1448 "use of undeclared SSA value name");
1449 return ParseFailure;
1450 }
1451
1452 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001453}
1454
Chris Lattner78276e32018-07-07 15:48:26 -07001455/// Parse a SSA operand for an instruction or statement.
1456///
James Molloy61a656c2018-07-22 15:45:24 -07001457/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001458///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001459ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001460 result.name = getTokenSpelling();
1461 result.number = 0;
1462 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001463 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1464 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001465
1466 // If we have an affine map ID, it is a result number.
1467 if (getToken().is(Token::hash_identifier)) {
1468 if (auto value = getToken().getHashIdentifierNumber())
1469 result.number = value.getValue();
1470 else
1471 return emitError("invalid SSA value result number");
1472 consumeToken(Token::hash_identifier);
1473 }
1474
Chris Lattner7f9cc272018-07-19 08:35:28 -07001475 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001476}
1477
1478/// Parse a (possibly empty) list of SSA operands.
1479///
1480/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1481/// ssa-use-list-opt ::= ssa-use-list?
1482///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001483ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001484FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001485 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001486 return ParseSuccess;
1487 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001488 SSAUseInfo result;
1489 if (parseSSAUse(result))
1490 return ParseFailure;
1491 results.push_back(result);
1492 return ParseSuccess;
1493 });
Chris Lattner78276e32018-07-07 15:48:26 -07001494}
1495
1496/// Parse an SSA use with an associated type.
1497///
1498/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001499template <typename ResultType>
1500ResultType FunctionParser::parseSSADefOrUseAndType(
1501 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001502
Chris Lattnerf7702a62018-07-23 17:30:01 -07001503 SSAUseInfo useInfo;
1504 if (parseSSAUse(useInfo) ||
1505 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1506 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001507
Chris Lattner7f9cc272018-07-19 08:35:28 -07001508 auto *type = parseType();
1509 if (!type)
1510 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001511
James Molloy61a656c2018-07-22 15:45:24 -07001512 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001513}
1514
Chris Lattner2c402672018-07-23 11:56:17 -07001515/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1516/// followed by a type list. If hasParens is true, then the operands are
1517/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001518///
Chris Lattner2c402672018-07-23 11:56:17 -07001519/// ssa-use-and-type-list[parens]
1520/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1521///
1522/// ssa-use-and-type-list[!parens]
1523/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001524///
Chris Lattner40746442018-07-21 14:32:09 -07001525template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001526ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001527 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1528
1529 // If we are in the parenthesized form and no paren exists, then we succeed
1530 // with an empty list.
1531 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001532 return ParseSuccess;
1533
Chris Lattner2c402672018-07-23 11:56:17 -07001534 SmallVector<SSAUseInfo, 4> valueIDs;
1535 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001536 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001537
1538 if (isParenthesized && !consumeIf(Token::r_paren))
1539 return emitError("expected ')' in operand list");
1540
1541 // If there were no operands, then there is no colon or type lists.
1542 if (valueIDs.empty())
1543 return ParseSuccess;
1544
Chris Lattner2c402672018-07-23 11:56:17 -07001545 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001546 if (parseToken(Token::colon, "expected ':' in operand list") ||
1547 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001548 return ParseFailure;
1549
1550 if (valueIDs.size() != types.size())
1551 return emitError("expected " + Twine(valueIDs.size()) +
1552 " types to match operand list");
1553
1554 results.reserve(valueIDs.size());
1555 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1556 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1557 results.push_back(cast<ValueTy>(value));
1558 else
1559 return ParseFailure;
1560 }
1561
1562 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001563}
1564
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001565/// Parse the CFG or MLFunc operation.
1566///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001567/// operation ::=
1568/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1569/// `:` function-type
1570///
1571ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001572FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001573 auto loc = getToken().getLoc();
1574
1575 StringRef resultID;
1576 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001577 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001578 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001579 if (parseToken(Token::equal, "expected '=' after SSA name"))
1580 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001581 }
1582
Chris Lattner85ee1512018-07-25 11:15:20 -07001583 Operation *op;
1584 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1585 op = parseCustomOperation(createOpFunc);
1586 else if (getToken().is(Token::string))
1587 op = parseVerboseOperation(createOpFunc);
1588 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001589 return emitError("expected operation name in quotes");
1590
Chris Lattner85ee1512018-07-25 11:15:20 -07001591 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001592 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001593 return ParseFailure;
1594
Chris Lattnerf7bdf952018-08-05 21:12:29 -07001595 // Apply location information to the instruction.
1596 // TODO(clattner): make this more principled. We shouldn't overwrite existing
1597 // location info, we should use a better serialized form, and we shouldn't
1598 // be using the :location attribute. This is also pretty inefficient.
1599 {
1600 auto &sourceMgr = getSourceMgr();
1601 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
1602 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
1603 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
1604 op->setAttr(builder.getIdentifier(":location"),
1605 builder.getIntegerAttr(locationEncoding));
1606 }
1607
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001608 // We just parsed an operation. If it is a recognized one, verify that it
1609 // is structurally as we expect. If not, produce an error with a reasonable
1610 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001611 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001612 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001613 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001614 }
1615
Chris Lattner7f9cc272018-07-19 08:35:28 -07001616 // If the instruction had a name, register it.
1617 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001618 if (op->getNumResults() == 0)
1619 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001620
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001621 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001622 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1623 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001624 }
1625
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001626 return ParseSuccess;
1627}
Chris Lattnere79379a2018-06-22 10:39:19 -07001628
Chris Lattner85ee1512018-07-25 11:15:20 -07001629Operation *FunctionParser::parseVerboseOperation(
1630 const CreateOperationFunction &createOpFunc) {
1631 auto name = getToken().getStringValue();
1632 if (name.empty())
1633 return (emitError("empty operation name is invalid"), nullptr);
1634
1635 consumeToken(Token::string);
1636
Chris Lattner992a1272018-08-07 12:02:37 -07001637 OperationState result(builder.getIdentifier(name));
1638
Chris Lattner85ee1512018-07-25 11:15:20 -07001639 // Parse the operand list.
1640 SmallVector<SSAUseInfo, 8> operandInfos;
1641
1642 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1643 parseOptionalSSAUseList(operandInfos) ||
1644 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1645 return nullptr;
1646 }
1647
Chris Lattner85ee1512018-07-25 11:15:20 -07001648 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001649 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001650 return nullptr;
1651 }
1652
1653 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1654 return nullptr;
1655
1656 auto typeLoc = getToken().getLoc();
1657 auto type = parseType();
1658 if (!type)
1659 return nullptr;
1660 auto fnType = dyn_cast<FunctionType>(type);
1661 if (!fnType)
1662 return (emitError(typeLoc, "expected function type"), nullptr);
1663
Chris Lattner992a1272018-08-07 12:02:37 -07001664 result.types.append(fnType->getResults().begin(), fnType->getResults().end());
1665
Chris Lattner85ee1512018-07-25 11:15:20 -07001666 // Check that we have the right number of types for the operands.
1667 auto operandTypes = fnType->getInputs();
1668 if (operandTypes.size() != operandInfos.size()) {
1669 auto plural = "s"[operandInfos.size() == 1];
1670 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1671 " operand type" + plural + " but had " +
1672 llvm::utostr(operandTypes.size())),
1673 nullptr);
1674 }
1675
1676 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001677 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001678 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1679 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001680 return nullptr;
1681 }
1682
Chris Lattner992a1272018-08-07 12:02:37 -07001683 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001684}
1685
1686namespace {
1687class CustomOpAsmParser : public OpAsmParser {
1688public:
1689 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1690 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1691
1692 /// This is an internal helper to parser a colon, we don't want to expose
1693 /// this to clients.
1694 bool internalParseColon(llvm::SMLoc *loc) {
1695 if (loc)
1696 *loc = parser.getToken().getLoc();
1697 return parser.parseToken(Token::colon, "expected ':'");
1698 }
1699
1700 //===--------------------------------------------------------------------===//
1701 // High level parsing methods.
1702 //===--------------------------------------------------------------------===//
1703
1704 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1705 if (loc)
1706 *loc = parser.getToken().getLoc();
1707 return parser.parseToken(Token::comma, "expected ','");
1708 }
1709
1710 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1711 return internalParseColon(loc) || !(result = parser.parseType());
1712 }
1713
1714 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1715 llvm::SMLoc *loc = nullptr) override {
1716 if (internalParseColon(loc))
1717 return true;
1718
1719 do {
1720 if (auto *type = parser.parseType())
1721 result.push_back(type);
1722 else
1723 return true;
1724
1725 } while (parser.consumeIf(Token::comma));
1726 return false;
1727 }
1728
Chris Lattner85cf26d2018-08-02 16:54:36 -07001729 /// Parse an arbitrary attribute and return it in result. This also adds the
1730 /// attribute to the specified attribute list with the specified name. this
1731 /// captures the location of the attribute in 'loc' if it is non-null.
1732 bool parseAttribute(Attribute *&result, const char *attrName,
1733 SmallVectorImpl<NamedAttribute> &attrs,
1734 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001735 if (loc)
1736 *loc = parser.getToken().getLoc();
1737 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001738 if (!result)
1739 return true;
1740
1741 attrs.push_back(
1742 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1743 return false;
1744 }
1745
1746 /// If a named attribute list is present, parse is into result.
1747 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1748 llvm::SMLoc *loc = nullptr) override {
1749 if (parser.getToken().isNot(Token::l_brace))
1750 return false;
1751 if (loc)
1752 *loc = parser.getToken().getLoc();
1753 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001754 }
1755
1756 bool parseOperand(OperandType &result) override {
1757 FunctionParser::SSAUseInfo useInfo;
1758 if (parser.parseSSAUse(useInfo))
1759 return true;
1760
1761 result = {useInfo.loc, useInfo.name, useInfo.number};
1762 return false;
1763 }
1764
1765 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1766 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001767 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001768 auto startLoc = parser.getToken().getLoc();
1769
Chris Lattner85cf26d2018-08-02 16:54:36 -07001770 // Handle delimiters.
1771 switch (delimiter) {
1772 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001773 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001774 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001775 if (parser.getToken().isNot(Token::l_paren))
1776 return false;
1777 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001778 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001779 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1780 return true;
1781 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001782 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001783 if (parser.getToken().isNot(Token::l_square))
1784 return false;
1785 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001786 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001787 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1788 return true;
1789 break;
1790 }
1791
1792 // Check for zero operands.
1793 if (parser.getToken().is(Token::percent_identifier)) {
1794 do {
1795 OperandType operand;
1796 if (parseOperand(operand))
1797 return true;
1798 result.push_back(operand);
1799 } while (parser.consumeIf(Token::comma));
1800 }
1801
Chris Lattner85cf26d2018-08-02 16:54:36 -07001802 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001803 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001804 switch (delimiter) {
1805 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001806 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001807 case Delimiter::OptionalParen:
1808 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001809 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1810 return true;
1811 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001812 case Delimiter::OptionalSquare:
1813 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001814 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1815 return true;
1816 break;
1817 }
1818
1819 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1820 emitError(startLoc,
1821 "expected " + Twine(requiredOperandCount) + " operands");
1822 return false;
1823 }
1824
1825 //===--------------------------------------------------------------------===//
1826 // Methods for interacting with the parser
1827 //===--------------------------------------------------------------------===//
1828
1829 Builder &getBuilder() const override { return parser.builder; }
1830
1831 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1832
1833 bool resolveOperand(OperandType operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001834 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001835 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1836 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001837 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1838 result.push_back(value);
1839 return false;
1840 }
1841 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001842 }
1843
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001844 /// Emit a diagnostic at the specified location and return true.
1845 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001846 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1847 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001848 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001849 }
1850
1851 bool didEmitError() const { return emittedError; }
1852
1853private:
1854 SMLoc nameLoc;
1855 StringRef opName;
1856 FunctionParser &parser;
1857 bool emittedError = false;
1858};
1859} // end anonymous namespace.
1860
1861Operation *FunctionParser::parseCustomOperation(
1862 const CreateOperationFunction &createOpFunc) {
1863 auto opLoc = getToken().getLoc();
1864 auto opName = getTokenSpelling();
1865 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1866
1867 auto *opDefinition = getOperationSet().lookup(opName);
1868 if (!opDefinition) {
1869 opAsmParser.emitError(opLoc, "is unknown");
1870 return nullptr;
1871 }
1872
1873 consumeToken();
1874
1875 // Have the op implementation take a crack and parsing this.
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001876 OperationState opState(builder.getIdentifier(opName));
1877 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1878 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001879
1880 // If it emitted an error, we failed.
1881 if (opAsmParser.didEmitError())
1882 return nullptr;
1883
1884 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001885 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001886}
1887
Chris Lattner48af7d12018-07-09 19:05:38 -07001888//===----------------------------------------------------------------------===//
1889// CFG Functions
1890//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001891
Chris Lattner4c95a502018-06-23 16:03:42 -07001892namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001893/// This is a specialized parser for CFGFunction's, maintaining the state
1894/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001895class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001896public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001897 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001898 : FunctionParser(state, Kind::CFGFunc), function(function),
1899 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001900
1901 ParseResult parseFunctionBody();
1902
1903private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001904 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001905 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001906
1907 /// This builder intentionally shadows the builder in the base class, with a
1908 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001909 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001910
Chris Lattner4c95a502018-06-23 16:03:42 -07001911 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001912 /// already exist. The location specified is the point of use, which allows
1913 /// us to diagnose references to blocks that are not defined precisely.
1914 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1915 auto &blockAndLoc = blocksByName[name];
1916 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001917 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001918 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001919 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001920 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001921 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001922
James Molloy61a656c2018-07-22 15:45:24 -07001923 ParseResult
1924 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1925 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001926 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1927 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001928
Chris Lattner48af7d12018-07-09 19:05:38 -07001929 ParseResult parseBasicBlock();
1930 OperationInst *parseCFGOperation();
1931 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001932};
1933} // end anonymous namespace
1934
James Molloy61a656c2018-07-22 15:45:24 -07001935/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001936/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001937///
1938/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1939///
1940ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1941 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1942 if (getToken().is(Token::r_brace))
1943 return ParseSuccess;
1944
1945 return parseCommaSeparatedList([&]() -> ParseResult {
1946 auto type = parseSSADefOrUseAndType<Type *>(
1947 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1948 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001949 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001950 return nullptr;
1951 return type;
1952 });
1953 return type ? ParseSuccess : ParseFailure;
1954 });
1955}
1956
Chris Lattner48af7d12018-07-09 19:05:38 -07001957ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001958 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001959 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1960 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001961
1962 // Make sure we have at least one block.
1963 if (getToken().is(Token::r_brace))
1964 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001965
1966 // Parse the list of blocks.
1967 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001968 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001969 return ParseFailure;
1970
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001971 // Verify that all referenced blocks were defined. Iteration over a
1972 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001973 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001974 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001975 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001976 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001977 "reference to an undefined basic block '" + elt.first() +
1978 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001979 }
1980
Chris Lattner40746442018-07-21 14:32:09 -07001981 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001982}
1983
1984/// Basic block declaration.
1985///
1986/// basic-block ::= bb-label instruction* terminator-stmt
1987/// bb-label ::= bb-id bb-arg-list? `:`
1988/// bb-id ::= bare-id
1989/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1990///
Chris Lattner48af7d12018-07-09 19:05:38 -07001991ParseResult CFGFunctionParser::parseBasicBlock() {
1992 SMLoc nameLoc = getToken().getLoc();
1993 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001994 if (parseToken(Token::bare_identifier, "expected basic block name"))
1995 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001996
Chris Lattner48af7d12018-07-09 19:05:38 -07001997 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001998
1999 // If this block has already been parsed, then this is a redefinition with the
2000 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002001 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002002 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2003
Chris Lattner78276e32018-07-07 15:48:26 -07002004 // If an argument list is present, parse it.
2005 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002006 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002007 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2008 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002009 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002010 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002011
James Molloy61a656c2018-07-22 15:45:24 -07002012 // Add the block to the function.
2013 function->push_back(block);
2014
Chris Lattnerf7702a62018-07-23 17:30:01 -07002015 if (parseToken(Token::colon, "expected ':' after basic block name"))
2016 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002017
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002018 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002019 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002020
Chris Lattner992a1272018-08-07 12:02:37 -07002021 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2022 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002023 };
2024
Chris Lattnered65a732018-06-28 20:45:33 -07002025 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002026 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002027 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002028 return ParseFailure;
2029 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002030
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002031 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002032 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002033
2034 return ParseSuccess;
2035}
2036
James Molloy4f788372018-07-24 15:01:27 -07002037ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2038 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2039 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2040 if (parseToken(Token::bare_identifier, "expected basic block name"))
2041 return ParseFailure;
2042
2043 if (!consumeIf(Token::l_paren))
2044 return ParseSuccess;
2045 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2046 parseToken(Token::r_paren, "expected ')' to close argument list"))
2047 return ParseFailure;
2048 return ParseSuccess;
2049}
2050
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002051/// Parse the terminator instruction for a basic block.
2052///
2053/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002054/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002055/// terminator-stmt ::=
2056/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2057/// terminator-stmt ::= `return` ssa-use-and-type-list?
2058///
Chris Lattner48af7d12018-07-09 19:05:38 -07002059TerminatorInst *CFGFunctionParser::parseTerminator() {
2060 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002061 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002062 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002063
Chris Lattner40746442018-07-21 14:32:09 -07002064 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002065 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002066
Chris Lattner2c402672018-07-23 11:56:17 -07002067 // Parse any operands.
2068 SmallVector<CFGValue *, 8> operands;
2069 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2070 return nullptr;
2071 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002072 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002073
2074 case Token::kw_br: {
2075 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002076 BasicBlock *destBB;
2077 SmallVector<CFGValue *, 4> values;
2078 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002079 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002080 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002081 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002082 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002083 }
James Molloy4f788372018-07-24 15:01:27 -07002084
2085 case Token::kw_cond_br: {
2086 consumeToken(Token::kw_cond_br);
2087 SSAUseInfo ssaUse;
2088 if (parseSSAUse(ssaUse))
2089 return nullptr;
2090 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2091 if (!cond)
2092 return (emitError("expected type was boolean (i1)"), nullptr);
2093 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2094 return nullptr;
2095
2096 BasicBlock *trueBlock;
2097 SmallVector<CFGValue *, 4> trueOperands;
2098 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2099 return nullptr;
2100
2101 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2102 return nullptr;
2103
2104 BasicBlock *falseBlock;
2105 SmallVector<CFGValue *, 4> falseOperands;
2106 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2107 return nullptr;
2108
2109 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2110 falseBlock);
2111 branch->addTrueOperands(trueOperands);
2112 branch->addFalseOperands(falseOperands);
2113 return branch;
2114 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002115 }
2116}
2117
Chris Lattner48af7d12018-07-09 19:05:38 -07002118//===----------------------------------------------------------------------===//
2119// ML Functions
2120//===----------------------------------------------------------------------===//
2121
2122namespace {
2123/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002124class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002125public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002126 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002127 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002128 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002129
2130 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002131
2132private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002133 MLFunction *function;
2134
2135 /// This builder intentionally shadows the builder in the base class, with a
2136 /// more specific builder type.
2137 MLFuncBuilder builder;
2138
2139 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002140 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002141 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002142 ParseResult parseElseClause(IfClause *elseClause);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002143 IntegerSet *parseCondition();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002144 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002145 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002146};
2147} // end anonymous namespace
2148
Chris Lattner48af7d12018-07-09 19:05:38 -07002149ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002150 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002151
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002152 // Parse statements in this function.
2153 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002154 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002155
Chris Lattner40746442018-07-21 14:32:09 -07002156 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002157}
2158
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002159/// For statement.
2160///
Chris Lattner48af7d12018-07-09 19:05:38 -07002161/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2162/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002163///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002164ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002165 consumeToken(Token::kw_for);
2166
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002167 // Parse induction variable
2168 if (getToken().isNot(Token::percent_identifier))
2169 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002170
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002171 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002172 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002173 consumeToken(Token::percent_identifier);
2174
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002175 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002176 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002177
2178 // Parse loop bounds
2179 AffineConstantExpr *lowerBound = parseIntConstant();
2180 if (!lowerBound)
2181 return ParseFailure;
2182
Chris Lattnerf7702a62018-07-23 17:30:01 -07002183 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2184 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002185
2186 AffineConstantExpr *upperBound = parseIntConstant();
2187 if (!upperBound)
2188 return ParseFailure;
2189
2190 // Parse step
2191 AffineConstantExpr *step = nullptr;
2192 if (consumeIf(Token::kw_step)) {
2193 step = parseIntConstant();
2194 if (!step)
2195 return ParseFailure;
2196 }
2197
2198 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002199 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2200
2201 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002202 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2203 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002204
2205 // If parsing of the for statement body fails,
2206 // MLIR contains for statement with those nested statements that have been
2207 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002208 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002209 return ParseFailure;
2210
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002211 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002212 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002214}
2215
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002216// This method is temporary workaround to parse simple loop bounds and
2217// step.
2218// TODO: remove this method once it's no longer used.
2219AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2220 if (getToken().isNot(Token::integer))
2221 return (emitError("expected non-negative integer for now"), nullptr);
2222
2223 auto val = getToken().getUInt64IntegerValue();
2224 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2225 return (emitError("constant too large for affineint"), nullptr);
2226 }
2227 consumeToken(Token::integer);
2228 return builder.getConstantExpr((int64_t)val.getValue());
2229}
2230
Uday Bondhugulabc535622018-08-07 14:24:38 -07002231/// Parse condition.
2232IntegerSet *MLFunctionParser::parseCondition() {
2233 return parseIntegerSetReference();
2234
2235 // TODO: Parse operands to the integer set.
2236}
2237
2238/// Parse an affine constraint.
2239/// affine-constraint ::= affine-expr `>=` `0`
2240/// | affine-expr `==` `0`
2241///
2242/// isEq is set to true if the parsed constraint is an equality, false if it is
2243/// an inequality (greater than or equal).
2244///
2245AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2246 AffineExpr *expr = parseAffineExpr();
2247 if (!expr)
2248 return nullptr;
2249
2250 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2251 getToken().is(Token::integer)) {
2252 auto dim = getToken().getUnsignedIntegerValue();
2253 if (dim.hasValue() && dim.getValue() == 0) {
2254 consumeToken(Token::integer);
2255 *isEq = false;
2256 return expr;
2257 }
2258 return (emitError("expected '0' after '>='"), nullptr);
2259 }
2260
2261 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2262 getToken().is(Token::integer)) {
2263 auto dim = getToken().getUnsignedIntegerValue();
2264 if (dim.hasValue() && dim.getValue() == 0) {
2265 consumeToken(Token::integer);
2266 *isEq = true;
2267 return expr;
2268 }
2269 return (emitError("expected '0' after '=='"), nullptr);
2270 }
2271
2272 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2273 nullptr);
2274}
2275
2276/// Parse an integer set definition.
2277/// integer-set-inline
2278/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2279/// affine-constraint-conjunction ::= /*empty*/
2280/// | affine-constraint (`,` affine-constraint)*
2281///
2282IntegerSet *AffineParser::parseIntegerSetInline() {
2283 unsigned numDims = 0, numSymbols = 0;
2284
2285 // List of dimensional identifiers.
2286 if (parseDimIdList(numDims))
2287 return nullptr;
2288
2289 // Symbols are optional.
2290 if (getToken().is(Token::l_square)) {
2291 if (parseSymbolIdList(numSymbols))
2292 return nullptr;
2293 }
2294
2295 if (parseToken(Token::colon, "expected ':' or '['") ||
2296 parseToken(Token::l_paren,
2297 "expected '(' at start of integer set constraint list"))
2298 return nullptr;
2299
2300 SmallVector<AffineExpr *, 4> constraints;
2301 SmallVector<bool, 4> isEqs;
2302 auto parseElt = [&]() -> ParseResult {
2303 bool isEq;
2304 auto *elt = parseAffineConstraint(&isEq);
2305 ParseResult res = elt ? ParseSuccess : ParseFailure;
2306 if (elt) {
2307 constraints.push_back(elt);
2308 isEqs.push_back(isEq);
2309 }
2310 return res;
2311 };
2312
2313 // Parse a list of affine constraints (comma-separated) .
2314 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2315 // affine-constraint)* `)
2316 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2317 return nullptr;
2318
2319 // Parsed a valid integer set.
2320 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2321}
2322
2323IntegerSet *Parser::parseIntegerSetInline() {
2324 return AffineParser(state).parseIntegerSetInline();
2325}
2326
2327/// Parse a reference to an integer set.
2328/// integer-set ::= integer-set-id | integer-set-inline
2329/// integer-set-id ::= `@@` suffix-id
2330///
2331IntegerSet *Parser::parseIntegerSetReference() {
2332 if (getToken().is(Token::double_at_identifier)) {
2333 // Parse integer set identifier and verify that it exists.
2334 StringRef integerSetId = getTokenSpelling().drop_front(2);
2335 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2336 return (emitError("undefined integer set id '" + integerSetId + "'"),
2337 nullptr);
2338 consumeToken(Token::double_at_identifier);
2339 return getState().integerSetDefinitions[integerSetId];
2340 }
2341 // Try to parse an inline integer set definition.
2342 return parseIntegerSetInline();
2343}
2344
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002345/// If statement.
2346///
Chris Lattner48af7d12018-07-09 19:05:38 -07002347/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2348/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2349/// ml-if-stmt ::= ml-if-head
2350/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002351///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002352ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002353 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002354
2355 if (parseToken(Token::l_paren, "expected '('"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002356 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002357
Uday Bondhugulabc535622018-08-07 14:24:38 -07002358 IntegerSet *condition = parseCondition();
2359 if (!condition)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002360 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002361
Uday Bondhugulabc535622018-08-07 14:24:38 -07002362 if (parseToken(Token::r_paren, "expected ')'"))
2363 return ParseFailure;
2364
2365 IfStmt *ifStmt = builder.createIf(condition);
Chris Lattnere787b322018-08-08 11:14:57 -07002366 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002367
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002368 // When parsing of an if statement body fails, the IR contains
2369 // the if statement with the portion of the body that has been
2370 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002371 if (parseStmtBlock(thenClause))
2372 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002373
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002374 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002375 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002376 if (parseElseClause(elseClause))
2377 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002378 }
2379
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002380 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002381 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002382
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002383 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002384}
2385
2386ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2387 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002388 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002389 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002390 }
2391
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002392 return parseStmtBlock(elseClause);
2393}
2394
2395///
2396/// Parse a list of statements ending with `return` or `}`
2397///
2398ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002399 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2400 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002401 };
2402
Chris Lattnere787b322018-08-08 11:14:57 -07002403 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002404
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002405 // Parse statements till we see '}' or 'return'.
2406 // Return statement is parsed separately to emit a more intuitive error
2407 // when '}' is missing after the return statement.
2408 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002409 switch (getToken().getKind()) {
2410 default:
2411 if (parseOperation(createOpFunc))
2412 return ParseFailure;
2413 break;
2414 case Token::kw_for:
2415 if (parseForStmt())
2416 return ParseFailure;
2417 break;
2418 case Token::kw_if:
2419 if (parseIfStmt())
2420 return ParseFailure;
2421 break;
2422 } // end switch
2423 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002424
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002425 // Parse the return statement.
2426 if (getToken().is(Token::kw_return))
2427 if (parseOperation(createOpFunc))
2428 return ParseFailure;
2429
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002430 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002431}
2432
2433///
2434/// Parse `{` ml-stmt* `}`
2435///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002436ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002437 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2438 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002439 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002440 return ParseFailure;
2441
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002442 return ParseSuccess;
2443}
2444
Chris Lattner4c95a502018-06-23 16:03:42 -07002445//===----------------------------------------------------------------------===//
2446// Top-level entity parsing.
2447//===----------------------------------------------------------------------===//
2448
Chris Lattner2e595eb2018-07-10 10:08:27 -07002449namespace {
2450/// This parser handles entities that are only valid at the top level of the
2451/// file.
2452class ModuleParser : public Parser {
2453public:
2454 explicit ModuleParser(ParserState &state) : Parser(state) {}
2455
2456 ParseResult parseModule();
2457
2458private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002459 ParseResult finalizeModule();
2460
Chris Lattner2e595eb2018-07-10 10:08:27 -07002461 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002462 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002463
2464 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002465 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2466 SmallVectorImpl<StringRef> &argNames);
2467 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2468 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002469 ParseResult parseExtFunc();
2470 ParseResult parseCFGFunc();
2471 ParseResult parseMLFunc();
2472};
2473} // end anonymous namespace
2474
2475/// Affine map declaration.
2476///
2477/// affine-map-def ::= affine-map-id `=` affine-map-inline
2478///
2479ParseResult ModuleParser::parseAffineMapDef() {
2480 assert(getToken().is(Token::hash_identifier));
2481
2482 StringRef affineMapId = getTokenSpelling().drop_front();
2483
2484 // Check for redefinitions.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002485 auto **entry = &getState().affineMapDefinitions[affineMapId];
2486 if (*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002487 return emitError("redefinition of affine map id '" + affineMapId + "'");
2488
2489 consumeToken(Token::hash_identifier);
2490
2491 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002492 if (parseToken(Token::equal,
2493 "expected '=' in affine map outlined definition"))
2494 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002495
Uday Bondhugulabc535622018-08-07 14:24:38 -07002496 *entry = parseAffineMapInline();
2497 if (!*entry)
2498 return ParseFailure;
2499
2500 return ParseSuccess;
2501}
2502
2503/// Integer set declaration.
2504///
2505/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2506///
2507ParseResult ModuleParser::parseIntegerSetDef() {
2508 assert(getToken().is(Token::double_at_identifier));
2509
2510 StringRef integerSetId = getTokenSpelling().drop_front(2);
2511
2512 // Check for redefinitions (a default entry is created if one doesn't exist)
2513 auto **entry = &getState().integerSetDefinitions[integerSetId];
2514 if (*entry)
2515 return emitError("redefinition of integer set id '" + integerSetId + "'");
2516
2517 consumeToken(Token::double_at_identifier);
2518
2519 // Parse the '='
2520 if (parseToken(Token::equal,
2521 "expected '=' in outlined integer set definition"))
2522 return ParseFailure;
2523
2524 *entry = parseIntegerSetInline();
2525 if (!*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002526 return ParseFailure;
2527
Chris Lattner2e595eb2018-07-10 10:08:27 -07002528 return ParseSuccess;
2529}
2530
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002531/// Parse a (possibly empty) list of MLFunction arguments with types.
2532///
2533/// ml-argument ::= ssa-id `:` type
2534/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2535///
2536ParseResult
2537ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2538 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002539 consumeToken(Token::l_paren);
2540
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002541 auto parseElt = [&]() -> ParseResult {
2542 // Parse argument name
2543 if (getToken().isNot(Token::percent_identifier))
2544 return emitError("expected SSA identifier");
2545
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002546 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002547 consumeToken(Token::percent_identifier);
2548 argNames.push_back(name);
2549
Chris Lattnerf7702a62018-07-23 17:30:01 -07002550 if (parseToken(Token::colon, "expected ':'"))
2551 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002552
2553 // Parse argument type
2554 auto elt = parseType();
2555 if (!elt)
2556 return ParseFailure;
2557 argTypes.push_back(elt);
2558
2559 return ParseSuccess;
2560 };
2561
Chris Lattner40746442018-07-21 14:32:09 -07002562 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002563}
2564
Chris Lattner2e595eb2018-07-10 10:08:27 -07002565/// Parse a function signature, starting with a name and including the parameter
2566/// list.
2567///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002568/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002569/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2570///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002571ParseResult
2572ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2573 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002574 if (getToken().isNot(Token::at_identifier))
2575 return emitError("expected a function identifier like '@foo'");
2576
2577 name = getTokenSpelling().drop_front();
2578 consumeToken(Token::at_identifier);
2579
2580 if (getToken().isNot(Token::l_paren))
2581 return emitError("expected '(' in function signature");
2582
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002583 SmallVector<Type *, 4> argTypes;
2584 ParseResult parseResult;
2585
2586 if (argNames)
2587 parseResult = parseMLArgumentList(argTypes, *argNames);
2588 else
2589 parseResult = parseTypeList(argTypes);
2590
2591 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002592 return ParseFailure;
2593
2594 // Parse the return type if present.
2595 SmallVector<Type *, 4> results;
2596 if (consumeIf(Token::arrow)) {
2597 if (parseTypeList(results))
2598 return ParseFailure;
2599 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002600 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002601 return ParseSuccess;
2602}
2603
2604/// External function declarations.
2605///
2606/// ext-func ::= `extfunc` function-signature
2607///
2608ParseResult ModuleParser::parseExtFunc() {
2609 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002610 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002611
2612 StringRef name;
2613 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002614 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002615 return ParseFailure;
2616
2617 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002618 auto *function = new ExtFunction(name, type);
2619 getModule()->getFunctions().push_back(function);
2620
2621 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002622 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002623 return emitError(loc,
2624 "redefinition of function named '" + name.str() + "'");
2625
Chris Lattner2e595eb2018-07-10 10:08:27 -07002626 return ParseSuccess;
2627}
2628
2629/// CFG function declarations.
2630///
2631/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2632///
2633ParseResult ModuleParser::parseCFGFunc() {
2634 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002635 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002636
2637 StringRef name;
2638 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002639 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002640 return ParseFailure;
2641
2642 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002643 auto *function = new CFGFunction(name, type);
2644 getModule()->getFunctions().push_back(function);
2645
2646 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002647 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002648 return emitError(loc,
2649 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002650
2651 return CFGFunctionParser(getState(), function).parseFunctionBody();
2652}
2653
2654/// ML function declarations.
2655///
2656/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2657///
2658ParseResult ModuleParser::parseMLFunc() {
2659 consumeToken(Token::kw_mlfunc);
2660
2661 StringRef name;
2662 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002663 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002664
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002665 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002666 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002667 return ParseFailure;
2668
2669 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002670 auto *function = MLFunction::create(name, type);
2671 getModule()->getFunctions().push_back(function);
2672
2673 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002674 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002675 return emitError(loc,
2676 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002677
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002678 // Create the parser.
2679 auto parser = MLFunctionParser(getState(), function);
2680
2681 // Add definitions of the function arguments.
2682 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2683 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2684 return ParseFailure;
2685 }
2686
2687 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002688}
2689
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002690/// Given an attribute that could refer to a function attribute in the remapping
2691/// table, walk it and rewrite it to use the mapped function. If it doesn't
2692/// refer to anything in the table, then it is returned unmodified.
2693static Attribute *
2694remapFunctionAttrs(Attribute *input,
2695 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2696 MLIRContext *context) {
2697 // Most attributes are trivially unrelated to function attributes, skip them
2698 // rapidly.
2699 if (!input->isOrContainsFunction())
2700 return input;
2701
2702 // If we have a function attribute, remap it.
2703 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2704 auto it = remappingTable.find(fnAttr);
2705 return it != remappingTable.end() ? it->second : input;
2706 }
2707
2708 // Otherwise, we must have an array attribute, remap the elements.
2709 auto *arrayAttr = cast<ArrayAttr>(input);
2710 SmallVector<Attribute *, 8> remappedElts;
2711 bool anyChange = false;
2712 for (auto *elt : arrayAttr->getValue()) {
2713 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2714 remappedElts.push_back(newElt);
2715 anyChange |= (elt != newElt);
2716 }
2717
2718 if (!anyChange)
2719 return input;
2720
2721 return ArrayAttr::get(remappedElts, context);
2722}
2723
2724/// Remap function attributes to resolve forward references to their actual
2725/// definition.
2726static void remapFunctionAttrsInOperation(
2727 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2728 for (auto attr : op->getAttrs()) {
2729 // Do the remapping, if we got the same thing back, then it must contain
2730 // functions that aren't getting remapped.
2731 auto *newVal =
2732 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2733 if (newVal == attr.second)
2734 continue;
2735
2736 // Otherwise, replace the existing attribute with the new one. It is safe
2737 // to mutate the attribute list while we walk it because underlying
2738 // attribute lists are uniqued and immortal.
2739 op->setAttr(attr.first, newVal);
2740 }
2741}
2742
Chris Lattner4613d9e2018-08-19 21:17:22 -07002743/// Finish the end of module parsing - when the result is valid, do final
2744/// checking.
2745ParseResult ModuleParser::finalizeModule() {
2746
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002747 // Resolve all forward references, building a remapping table of attributes.
2748 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002749 for (auto forwardRef : getState().functionForwardRefs) {
2750 auto name = forwardRef.first;
2751
2752 // Resolve the reference.
2753 auto *resolvedFunction = getModule()->getNamedFunction(name);
2754 if (!resolvedFunction)
2755 return emitError(forwardRef.second.second,
2756 "reference to undefined function '" + name.str() + "'");
2757
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002758 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2759 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002760 }
2761
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002762 // If there was nothing to remap, then we're done.
2763 if (remappingTable.empty())
2764 return ParseSuccess;
2765
2766 // Otherwise, walk the entire module replacing uses of one attribute set with
2767 // the correct ones.
2768 for (auto &fn : *getModule()) {
2769 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2770 for (auto &bb : *cfgFn) {
2771 for (auto &inst : bb) {
2772 remapFunctionAttrsInOperation(&inst, remappingTable);
2773 }
2774 }
2775 }
2776
2777 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2778 auto *mlFn = dyn_cast<MLFunction>(&fn);
2779 if (!mlFn)
2780 continue;
2781
2782 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2783 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2784 : remappingTable(remappingTable) {}
2785 void visitOperationStmt(OperationStmt *opStmt) {
2786 remapFunctionAttrsInOperation(opStmt, remappingTable);
2787 }
2788
2789 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2790 };
2791
2792 MLFnWalker(remappingTable).walk(mlFn);
2793 }
2794
2795 // Now that all references to the forward definition placeholders are
2796 // resolved, we can deallocate the placeholders.
2797 for (auto forwardRef : getState().functionForwardRefs)
2798 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002799 return ParseSuccess;
2800}
2801
Chris Lattnere79379a2018-06-22 10:39:19 -07002802/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002803ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002804 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002805 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002806 default:
2807 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002808 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002809
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002810 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002811 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002812 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002813
2814 // If we got an error token, then the lexer already emitted an error, just
2815 // stop. Someday we could introduce error recovery if there was demand for
2816 // it.
2817 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002818 return ParseFailure;
2819
2820 case Token::hash_identifier:
2821 if (parseAffineMapDef())
2822 return ParseFailure;
2823 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002824
Uday Bondhugulabc535622018-08-07 14:24:38 -07002825 case Token::double_at_identifier:
2826 if (parseIntegerSetDef())
2827 return ParseFailure;
2828 break;
2829
Chris Lattnere79379a2018-06-22 10:39:19 -07002830 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002831 if (parseExtFunc())
2832 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002833 break;
2834
Chris Lattner4c95a502018-06-23 16:03:42 -07002835 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002836 if (parseCFGFunc())
2837 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002838 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002839
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002840 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002841 if (parseMLFunc())
2842 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002843 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002844 }
2845 }
2846}
2847
2848//===----------------------------------------------------------------------===//
2849
Jacques Pienaar7b829702018-07-03 13:24:09 -07002850void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2851 const auto &sourceMgr = *error.getSourceMgr();
2852 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2853}
2854
Chris Lattnere79379a2018-06-22 10:39:19 -07002855/// This parses the file specified by the indicated SourceMgr and returns an
2856/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002857Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002858 SMDiagnosticHandlerTy errorReporter) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002859 if (!errorReporter)
2860 errorReporter = defaultErrorReporter;
2861
2862 // We are going to replace the context's handler and redirect it to use the
2863 // error reporter. Save the existing handler and reinstate it when we're
2864 // done.
2865 auto existingContextHandler = context->getDiagnosticHandler();
2866
2867 // Install a new handler that uses the error reporter.
2868 context->registerDiagnosticHandler([&](Attribute *location, StringRef message,
2869 MLIRContext::DiagnosticKind kind) {
2870 auto offset = cast<IntegerAttr>(location)->getValue();
2871 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2872 auto ptr = mainBuffer->getBufferStart() + offset;
2873 SourceMgr::DiagKind diagKind;
2874 switch (kind) {
2875 case MLIRContext::DiagnosticKind::Error:
2876 diagKind = SourceMgr::DK_Error;
2877 break;
2878 case MLIRContext::DiagnosticKind::Warning:
2879 diagKind = SourceMgr::DK_Warning;
2880 break;
2881 case MLIRContext::DiagnosticKind::Note:
2882 diagKind = SourceMgr::DK_Note;
2883 break;
2884 }
2885 errorReporter(
2886 sourceMgr.GetMessage(SMLoc::getFromPointer(ptr), diagKind, message));
2887 });
2888
Chris Lattner2e595eb2018-07-10 10:08:27 -07002889 // This is the result module we are parsing into.
2890 std::unique_ptr<Module> module(new Module(context));
2891
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002892 ParserState state(sourceMgr, module.get(), errorReporter);
2893 if (ModuleParser(state).parseModule()) {
2894 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002895 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002896 }
Chris Lattner21e67f62018-07-06 10:46:19 -07002897
2898 // Make sure the parse module has no other structural problems detected by the
2899 // verifier.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002900 std::string errorResult;
2901 module->verify(&errorResult);
2902
2903 // We don't have location information for general verifier errors, so emit the
2904 // error on the first line.
2905 if (!errorResult.empty()) {
2906 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2907 errorReporter(sourceMgr.GetMessage(
2908 SMLoc::getFromPointer(mainBuffer->getBufferStart()),
2909 SourceMgr::DK_Error, errorResult));
2910 return nullptr;
2911 }
2912
2913 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002914 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002915}