blob: 1d73d5b715ae8fdebfd389950188d5755aa458eb [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
30#include "mlir/IR/OperationSet.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070031#include "mlir/IR/Types.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070032#include "llvm/Support/SourceMgr.h"
33using namespace mlir;
34using llvm::SourceMgr;
Chris Lattner4c95a502018-06-23 16:03:42 -070035using llvm::SMLoc;
Chris Lattnere79379a2018-06-22 10:39:19 -070036
Chris Lattnerf7e22732018-06-22 22:03:48 -070037/// Simple enum to make code read better in cases that would otherwise return a
38/// bool value. Failure is "true" in a boolean context.
Chris Lattnere79379a2018-06-22 10:39:19 -070039enum ParseResult {
40 ParseSuccess,
41 ParseFailure
42};
43
Chris Lattner48af7d12018-07-09 19:05:38 -070044namespace {
45class Parser;
46
47/// This class refers to all of the state maintained globally by the parser,
48/// such as the current lexer position etc. The Parser base class provides
49/// methods to access this.
50class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070051public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070052 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070053 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 : context(module->getContext()), module(module),
55 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Jacques Pienaard4c784e2018-07-11 00:07:36 -070056 errorReporter(errorReporter) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070057
58 // A map from affine map identifier to AffineMap.
59 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070060
Chris Lattnere79379a2018-06-22 10:39:19 -070061private:
Chris Lattner48af7d12018-07-09 19:05:38 -070062 ParserState(const ParserState &) = delete;
63 void operator=(const ParserState &) = delete;
64
65 friend class Parser;
66
67 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070068 MLIRContext *const context;
69
70 // This is the module we are parsing into.
71 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070072
73 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070074 Lexer lex;
75
76 // This is the next token that hasn't been consumed yet.
77 Token curToken;
78
Jacques Pienaar9c411be2018-06-24 19:17:35 -070079 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070080 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner48af7d12018-07-09 19:05:38 -070081};
82} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070083
Chris Lattner48af7d12018-07-09 19:05:38 -070084namespace {
85
86/// This class implement support for parsing global entities like types and
87/// shared entities like SSA names. It is intended to be subclassed by
88/// specialized subparsers that include state, e.g. when a local symbol table.
89class Parser {
90public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070091 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070092
Chris Lattner2e595eb2018-07-10 10:08:27 -070093 Parser(ParserState &state) : builder(state.context), state(state) {}
94
95 // Helper methods to get stuff from the parser-global state.
96 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -070097 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -070098 Module *getModule() { return state.module; }
Chris Lattner48af7d12018-07-09 19:05:38 -070099
100 /// Return the current token the parser is inspecting.
101 const Token &getToken() const { return state.curToken; }
102 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700103
104 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700105 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700106 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700107 }
108 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700109
110 /// Advance the current lexer onto the next token.
111 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700112 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700113 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700114 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700115 }
116
117 /// Advance the current lexer onto the next token, asserting what the expected
118 /// current token is. This is preferred to the above method because it leads
119 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700120 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700121 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700122 consumeToken();
123 }
124
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700125 /// If the current token has the specified kind, consume it and return true.
126 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700127 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700128 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700129 return false;
130 consumeToken(kind);
131 return true;
132 }
133
Chris Lattner8da0c282018-06-29 11:15:56 -0700134 ParseResult parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700135 const std::function<ParseResult()> &parseElement,
136 bool allowEmptyList = true);
137
Chris Lattnerf7e22732018-06-22 22:03:48 -0700138 // We have two forms of parsing methods - those that return a non-null
139 // pointer on success, and those that return a ParseResult to indicate whether
140 // they returned a failure. The second class fills in by-reference arguments
141 // as the results of their action.
142
Chris Lattnere79379a2018-06-22 10:39:19 -0700143 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700144 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700145 Type *parseElementType();
146 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700147 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700148 Type *parseTensorType();
149 Type *parseMemRefType();
150 Type *parseFunctionType();
151 Type *parseType();
152 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700153
Chris Lattner7121b802018-07-04 20:45:39 -0700154 // Attribute parsing.
155 Attribute *parseAttribute();
156 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
157
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700158 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700159 AffineMap *parseAffineMapInline();
MLIR Teamf85a6262018-06-27 11:03:08 -0700160
Chris Lattner78276e32018-07-07 15:48:26 -0700161 // SSA
162 ParseResult parseSSAUse();
163 ParseResult parseOptionalSSAUseList(Token::Kind endToken);
164 ParseResult parseSSAUseAndType();
165 ParseResult parseOptionalSSAUseAndTypeList(Token::Kind endToken);
166
Chris Lattner48af7d12018-07-09 19:05:38 -0700167private:
168 // The Parser is subclassed and reinstantiated. Do not add additional
169 // non-trivial state here, add it to the ParserState class.
170 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700171};
172} // end anonymous namespace
173
174//===----------------------------------------------------------------------===//
175// Helper methods.
176//===----------------------------------------------------------------------===//
177
Chris Lattner4c95a502018-06-23 16:03:42 -0700178ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700179 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700180 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700181 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700182 return ParseFailure;
183
Chris Lattner48af7d12018-07-09 19:05:38 -0700184 auto &sourceMgr = state.lex.getSourceMgr();
185 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700186 return ParseFailure;
187}
188
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700189/// Parse a comma-separated list of elements, terminated with an arbitrary
190/// token. This allows empty lists if allowEmptyList is true.
191///
192/// abstract-list ::= rightToken // if allowEmptyList == true
193/// abstract-list ::= element (',' element)* rightToken
194///
195ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700196parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700197 const std::function<ParseResult()> &parseElement,
198 bool allowEmptyList) {
199 // Handle the empty case.
Chris Lattner48af7d12018-07-09 19:05:38 -0700200 if (getToken().is(rightToken)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700201 if (!allowEmptyList)
202 return emitError("expected list element");
203 consumeToken(rightToken);
204 return ParseSuccess;
205 }
206
207 // Non-empty case starts with an element.
208 if (parseElement())
209 return ParseFailure;
210
211 // Otherwise we have a list of comma separated elements.
212 while (consumeIf(Token::comma)) {
213 if (parseElement())
214 return ParseFailure;
215 }
216
217 // Consume the end character.
218 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700219 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
220 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700221
222 return ParseSuccess;
223}
Chris Lattnere79379a2018-06-22 10:39:19 -0700224
225//===----------------------------------------------------------------------===//
226// Type Parsing
227//===----------------------------------------------------------------------===//
228
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700229/// Parse the low-level fixed dtypes in the system.
230///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700231/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
232/// primitive-type ::= integer-type
233/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700234///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700235Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700236 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700237 default:
238 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700239 case Token::kw_bf16:
240 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700241 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700242 case Token::kw_f16:
243 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700244 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700245 case Token::kw_f32:
246 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700247 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700248 case Token::kw_f64:
249 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700250 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700251 case Token::kw_affineint:
252 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700253 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700254 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700255 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700256 if (!width.hasValue())
257 return (emitError("invalid integer width"), nullptr);
258 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700259 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700260 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700261 }
262}
263
264/// Parse the element type of a tensor or memref type.
265///
266/// element-type ::= primitive-type | vector-type
267///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700268Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700269 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700270 return parseVectorType();
271
272 return parsePrimitiveType();
273}
274
275/// Parse a vector type.
276///
277/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
278/// const-dimension-list ::= (integer-literal `x`)+
279///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700280VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700281 consumeToken(Token::kw_vector);
282
283 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700284 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700285
Chris Lattner48af7d12018-07-09 19:05:38 -0700286 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700287 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700288
289 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700290 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700291 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700292 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700293 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700294 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295 dimensions.push_back(dimension.getValue());
296
297 consumeToken(Token::integer);
298
299 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700300 if (getToken().isNot(Token::bare_identifier) ||
301 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700302 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700303
304 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700305 if (getTokenSpelling().size() != 1)
306 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700307
308 // Consume the 'x'.
309 consumeToken(Token::bare_identifier);
310 }
311
312 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700313 auto *elementType = parsePrimitiveType();
314 if (!elementType)
315 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700316
317 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700318 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700319
Chris Lattnerf7e22732018-06-22 22:03:48 -0700320 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321}
322
323/// Parse a dimension list of a tensor or memref type. This populates the
324/// dimension list, returning -1 for the '?' dimensions.
325///
326/// dimension-list-ranked ::= (dimension `x`)*
327/// dimension ::= `?` | integer-literal
328///
329ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700330 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331 if (consumeIf(Token::question)) {
332 dimensions.push_back(-1);
333 } else {
334 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700335 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
337 return emitError("invalid dimension");
338 dimensions.push_back((int)dimension.getValue());
339 consumeToken(Token::integer);
340 }
341
342 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700343 if (getToken().isNot(Token::bare_identifier) ||
344 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700345 return emitError("expected 'x' in dimension list");
346
347 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700348 if (getTokenSpelling().size() != 1)
349 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700350
351 // Consume the 'x'.
352 consumeToken(Token::bare_identifier);
353 }
354
355 return ParseSuccess;
356}
357
358/// Parse a tensor type.
359///
360/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
361/// dimension-list ::= dimension-list-ranked | `??`
362///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700363Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700364 consumeToken(Token::kw_tensor);
365
366 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700367 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700368
369 bool isUnranked;
370 SmallVector<int, 4> dimensions;
371
372 if (consumeIf(Token::questionquestion)) {
373 isUnranked = true;
374 } else {
375 isUnranked = false;
376 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700377 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700378 }
379
380 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700381 auto elementType = parseElementType();
382 if (!elementType)
383 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700384
385 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700386 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700387
MLIR Team355ec862018-06-23 18:09:09 -0700388 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700389 return builder.getTensorType(elementType);
390 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700391}
392
393/// Parse a memref type.
394///
395/// memref-type ::= `memref` `<` dimension-list-ranked element-type
396/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
397///
398/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
399/// memory-space ::= integer-literal /* | TODO: address-space-id */
400///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700401Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700402 consumeToken(Token::kw_memref);
403
404 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700405 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700406
407 SmallVector<int, 4> dimensions;
408 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700409 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700410
411 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700412 auto elementType = parseElementType();
413 if (!elementType)
414 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700415
416 // TODO: Parse semi-affine-map-composition.
417 // TODO: Parse memory-space.
418
419 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700420 return (emitError("expected '>' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700421
Chris Lattnerf7e22732018-06-22 22:03:48 -0700422 // FIXME: Add an IR representation for memref types.
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700423 return builder.getIntegerType(1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700424}
425
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426/// Parse a function type.
427///
428/// function-type ::= type-list-parens `->` type-list
429///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700430Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700431 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700432
Chris Lattnerf7e22732018-06-22 22:03:48 -0700433 SmallVector<Type*, 4> arguments;
434 if (parseTypeList(arguments))
435 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700436
437 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700438 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700439
Chris Lattnerf7e22732018-06-22 22:03:48 -0700440 SmallVector<Type*, 4> results;
441 if (parseTypeList(results))
442 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700443
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700444 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700445}
446
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700447/// Parse an arbitrary type.
448///
449/// type ::= primitive-type
450/// | vector-type
451/// | tensor-type
452/// | memref-type
453/// | function-type
454/// element-type ::= primitive-type | vector-type
455///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700456Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700457 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700458 case Token::kw_memref: return parseMemRefType();
459 case Token::kw_tensor: return parseTensorType();
460 case Token::kw_vector: return parseVectorType();
461 case Token::l_paren: return parseFunctionType();
462 default:
463 return parsePrimitiveType();
464 }
465}
466
467/// Parse a "type list", which is a singular type, or a parenthesized list of
468/// types.
469///
470/// type-list ::= type-list-parens | type
471/// type-list-parens ::= `(` `)`
472/// | `(` type (`,` type)* `)`
473///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700474ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
475 auto parseElt = [&]() -> ParseResult {
476 auto elt = parseType();
477 elements.push_back(elt);
478 return elt ? ParseSuccess : ParseFailure;
479 };
480
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700481 // If there is no parens, then it must be a singular type.
482 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700483 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484
Chris Lattnerf7e22732018-06-22 22:03:48 -0700485 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700486 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700487
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700488 return ParseSuccess;
489}
490
Chris Lattner4c95a502018-06-23 16:03:42 -0700491//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700492// Attribute parsing.
493//===----------------------------------------------------------------------===//
494
495
496/// Attribute parsing.
497///
498/// attribute-value ::= bool-literal
499/// | integer-literal
500/// | float-literal
501/// | string-literal
502/// | `[` (attribute-value (`,` attribute-value)*)? `]`
503///
504Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700505 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700506 case Token::kw_true:
507 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700508 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700509 case Token::kw_false:
510 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700511 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700512
513 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700514 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700515 if (!val.hasValue() || (int64_t)val.getValue() < 0)
516 return (emitError("integer too large for attribute"), nullptr);
517 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700518 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700519 }
520
521 case Token::minus: {
522 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700523 if (getToken().is(Token::integer)) {
524 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700525 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
526 return (emitError("integer too large for attribute"), nullptr);
527 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700528 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700529 }
530
531 return (emitError("expected constant integer or floating point value"),
532 nullptr);
533 }
534
535 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700536 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700537 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700538 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700539 }
540
541 case Token::l_bracket: {
542 consumeToken(Token::l_bracket);
543 SmallVector<Attribute*, 4> elements;
544
545 auto parseElt = [&]() -> ParseResult {
546 elements.push_back(parseAttribute());
547 return elements.back() ? ParseSuccess : ParseFailure;
548 };
549
550 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
551 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700552 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700553 }
554 default:
555 // TODO: Handle floating point.
556 return (emitError("expected constant attribute value"), nullptr);
557 }
558}
559
Chris Lattner7121b802018-07-04 20:45:39 -0700560/// Attribute dictionary.
561///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700562/// attribute-dict ::= `{` `}`
563/// | `{` attribute-entry (`,` attribute-entry)* `}`
564/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700565///
566ParseResult Parser::parseAttributeDict(
567 SmallVectorImpl<NamedAttribute> &attributes) {
568 consumeToken(Token::l_brace);
569
570 auto parseElt = [&]() -> ParseResult {
571 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700572 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
573 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700574 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700575 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700576 consumeToken();
577
578 if (!consumeIf(Token::colon))
579 return emitError("expected ':' in attribute list");
580
581 auto attr = parseAttribute();
582 if (!attr) return ParseFailure;
583
584 attributes.push_back({nameId, attr});
585 return ParseSuccess;
586 };
587
588 if (parseCommaSeparatedList(Token::r_brace, parseElt))
589 return ParseFailure;
590
591 return ParseSuccess;
592}
593
594//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700595// Polyhedral structures.
596//===----------------------------------------------------------------------===//
597
Chris Lattner2e595eb2018-07-10 10:08:27 -0700598/// Lower precedence ops (all at the same precedence level). LNoOp is false in
599/// the boolean sense.
600enum AffineLowPrecOp {
601 /// Null value.
602 LNoOp,
603 Add,
604 Sub
605};
MLIR Teamf85a6262018-06-27 11:03:08 -0700606
Chris Lattner2e595eb2018-07-10 10:08:27 -0700607/// Higher precedence ops - all at the same precedence level. HNoOp is false in
608/// the boolean sense.
609enum AffineHighPrecOp {
610 /// Null value.
611 HNoOp,
612 Mul,
613 FloorDiv,
614 CeilDiv,
615 Mod
616};
Chris Lattner7121b802018-07-04 20:45:39 -0700617
Chris Lattner2e595eb2018-07-10 10:08:27 -0700618namespace {
619/// This is a specialized parser for AffineMap's, maintaining the state
620/// transient to their bodies.
621class AffineMapParser : public Parser {
622public:
623 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700624
Chris Lattner2e595eb2018-07-10 10:08:27 -0700625 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700626
Chris Lattner2e595eb2018-07-10 10:08:27 -0700627private:
628 unsigned getNumDims() const { return dims.size(); }
629 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700630
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700631 /// Returns true if the only identifiers the parser accepts in affine
632 /// expressions are symbolic identifiers.
633 bool isPureSymbolic() const { return pureSymbolic; }
634 void setSymbolicParsing(bool val) { pureSymbolic = val; }
635
Chris Lattner2e595eb2018-07-10 10:08:27 -0700636 // Binary affine op parsing.
637 AffineLowPrecOp consumeIfLowPrecOp();
638 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700639
Chris Lattner2e595eb2018-07-10 10:08:27 -0700640 // Identifier lists for polyhedral structures.
641 ParseResult parseDimIdList();
642 ParseResult parseSymbolIdList();
643 ParseResult parseDimOrSymbolId(bool isDim);
644
645 AffineExpr *parseAffineExpr();
646 AffineExpr *parseParentheticalExpr();
647 AffineExpr *parseNegateExpression(AffineExpr *lhs);
648 AffineExpr *parseIntegerExpr();
649 AffineExpr *parseBareIdExpr();
650
651 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
652 AffineExpr *rhs);
653 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
654 AffineExpr *rhs);
655 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
656 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
657 AffineLowPrecOp llhsOp);
658 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
659 AffineHighPrecOp llhsOp);
660
661private:
662 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
663 llvm::StringMap<unsigned> dims;
664 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700665 /// True if the parser should allow only symbolic identifiers in affine
666 /// expressions.
667 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700668};
669} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700670
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700671/// Create an affine binary high precedence op expression (mul's, div's, mod)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700672AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
673 AffineExpr *lhs,
674 AffineExpr *rhs) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700675 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700676 switch (op) {
677 case Mul:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700678 if (!lhs->isSymbolic() && !rhs->isSymbolic()) {
679 emitError("non-affine expression: at least one of the multiply "
680 "operands has to be either a constant or symbolic");
681 return nullptr;
682 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700683 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700684 case FloorDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700685 if (!rhs->isSymbolic()) {
686 emitError("non-affine expression: right operand of floordiv "
687 "has to be either a constant or symbolic");
688 return nullptr;
689 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700690 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700691 case CeilDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700692 if (!rhs->isSymbolic()) {
693 emitError("non-affine expression: right operand of ceildiv "
694 "has to be either a constant or symbolic");
695 return nullptr;
696 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700697 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700698 case Mod:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700699 if (!rhs->isSymbolic()) {
700 emitError("non-affine expression: right operand of mod "
701 "has to be either a constant or symbolic");
702 return nullptr;
703 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700704 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700705 case HNoOp:
706 llvm_unreachable("can't create affine expression for null high prec op");
707 return nullptr;
708 }
709}
710
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700711/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700712AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
713 AffineExpr *lhs,
714 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700715 switch (op) {
716 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700717 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700718 case AffineLowPrecOp::Sub:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700719 return builder.getSubExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700720 case AffineLowPrecOp::LNoOp:
721 llvm_unreachable("can't create affine expression for null low prec op");
722 return nullptr;
723 }
724}
725
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700726/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700727/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700728AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700729 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700730 case Token::plus:
731 consumeToken(Token::plus);
732 return AffineLowPrecOp::Add;
733 case Token::minus:
734 consumeToken(Token::minus);
735 return AffineLowPrecOp::Sub;
736 default:
737 return AffineLowPrecOp::LNoOp;
738 }
739}
740
741/// Consume this token if it is a higher precedence affine op (there are only
742/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700743AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700744 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700745 case Token::star:
746 consumeToken(Token::star);
747 return Mul;
748 case Token::kw_floordiv:
749 consumeToken(Token::kw_floordiv);
750 return FloorDiv;
751 case Token::kw_ceildiv:
752 consumeToken(Token::kw_ceildiv);
753 return CeilDiv;
754 case Token::kw_mod:
755 consumeToken(Token::kw_mod);
756 return Mod;
757 default:
758 return HNoOp;
759 }
760}
761
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700762/// Parse a high precedence op expression list: mul, div, and mod are high
763/// precedence binary ops, i.e., parse a
764/// expr_1 op_1 expr_2 op_2 ... expr_n
765/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
766/// All affine binary ops are left associative.
767/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
768/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
769/// null.
770AffineExpr *
Chris Lattner2e595eb2018-07-10 10:08:27 -0700771AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
772 AffineHighPrecOp llhsOp) {
773 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700774 if (!lhs)
775 return nullptr;
776
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700777 // Found an LHS. Parse the remaining expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700778 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700779 if (llhs) {
780 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
781 if (!expr)
782 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700783 return parseAffineHighPrecOpExpr(expr, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700784 }
785 // No LLHS, get RHS
Chris Lattner2e595eb2018-07-10 10:08:27 -0700786 return parseAffineHighPrecOpExpr(lhs, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700787 }
788
789 // This is the last operand in this expression.
790 if (llhs)
791 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
792
793 // No llhs, 'lhs' itself is the expression.
794 return lhs;
795}
796
797/// Parse an affine expression inside parentheses.
798///
799/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700800AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700801 if (!consumeIf(Token::l_paren))
802 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700803 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700804 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700805 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700806 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700807 return nullptr;
808 if (!consumeIf(Token::r_paren))
809 return (emitError("expected ')'"), nullptr);
810 return expr;
811}
812
813/// Parse the negation expression.
814///
815/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700816AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700817 if (!consumeIf(Token::minus))
818 return (emitError("expected '-'"), nullptr);
819
Chris Lattner2e595eb2018-07-10 10:08:27 -0700820 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700821 // Since negation has the highest precedence of all ops (including high
822 // precedence ops) but lower than parentheses, we are only going to use
823 // parseAffineOperandExpr instead of parseAffineExpr here.
824 if (!operand)
825 // Extra error message although parseAffineOperandExpr would have
826 // complained. Leads to a better diagnostic.
827 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700828 auto *minusOne = builder.getConstantExpr(-1);
829 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700830}
831
832/// Parse a bare id that may appear in an affine expression.
833///
834/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700835AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700836 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700837 return (emitError("expected bare identifier"), nullptr);
838
Chris Lattner48af7d12018-07-09 19:05:38 -0700839 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700840 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700841 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700842 if (isPureSymbolic())
843 return (emitError("identifier used is not a symbolic identifier"),
844 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700845 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700846 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700847 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700848
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700849 if (symbols.count(sRef)) {
850 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700851 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700852 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700853
854 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855}
856
857/// Parse a positive integral constant appearing in an affine expression.
858///
859/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700860AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700861 // No need to handle negative numbers separately here. They are naturally
862 // handled via the unary negation operator, although (FIXME) MININT_64 still
863 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700864 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700865 return (emitError("expected integer"), nullptr);
866
Chris Lattner48af7d12018-07-09 19:05:38 -0700867 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700868 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
869 return (emitError("constant too large for affineint"), nullptr);
870 }
871 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700872 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700873}
874
875/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700876/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
877/// operator, the rhs of which is being parsed. This is used to determine
878/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700879// Eg: for an expression without parentheses (like i + j + k + l), each
880// of the four identifiers is an operand. For i + j*k + l, j*k is not an
881// operand expression, it's an op expression and will be parsed via
882// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
883// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700884AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700885 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700886 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700887 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700888 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700889 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700890 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700891 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700892 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700893 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700894 case Token::kw_ceildiv:
895 case Token::kw_floordiv:
896 case Token::kw_mod:
897 case Token::plus:
898 case Token::star:
899 if (lhs)
900 emitError("missing right operand of binary operator");
901 else
902 emitError("missing left operand of binary operator");
903 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700904 default:
905 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700906 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700907 else
908 emitError("expected affine expression");
909 return nullptr;
910 }
911}
912
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700913/// Parse affine expressions that are bare-id's, integer constants,
914/// parenthetical affine expressions, and affine op expressions that are a
915/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700916///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700917/// All binary op's associate from left to right.
918///
919/// {add, sub} have lower precedence than {mul, div, and mod}.
920///
Uday Bondhugula76345202018-07-09 13:47:52 -0700921/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
922/// ceildiv, and mod are at the same higher precedence level. Negation has
923/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700924///
925/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700926/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
927/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
928/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700929/// associativity.
930///
931/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700932/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
933/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700934AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
935 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700936 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700937 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700938 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700939
940 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700941 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700942 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700943 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700944 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700945 }
946 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700947 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700948 }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700949 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700950 // We have a higher precedence op here. Get the rhs operand for the llhs
951 // through parseAffineHighPrecOpExpr.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700952 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 if (!highRes)
954 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700955
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700956 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700957 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700958 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700959 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700960
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961 // Recurse for subsequent low prec op's after the affine high prec op
962 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700963 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
964 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700965 return expr;
966 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700967 // Last operand in the expression list.
968 if (llhs)
969 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
970 // No llhs, 'lhs' itself is the expression.
971 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700972}
973
974/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700975/// affine-expr ::= `(` affine-expr `)`
976/// | `-` affine-expr
977/// | affine-expr `+` affine-expr
978/// | affine-expr `-` affine-expr
979/// | affine-expr `*` affine-expr
980/// | affine-expr `floordiv` affine-expr
981/// | affine-expr `ceildiv` affine-expr
982/// | affine-expr `mod` affine-expr
983/// | bare-id
984/// | integer-literal
985///
986/// Additional conditions are checked depending on the production. For eg., one
987/// of the operands for `*` has to be either constant/symbolic; the second
988/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700989AffineExpr *AffineMapParser::parseAffineExpr() {
990 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700991}
992
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700993/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -0700994/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700995/// identifier. 'dim': whether it's the dim list or symbol list that is being
996/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700997ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700998 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700999 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001000 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001001 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001002 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001003 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001004 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001005 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001006 if (isDim)
1007 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001008 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001009 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001010 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001011}
1012
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001013/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014ParseResult AffineMapParser::parseSymbolIdList() {
1015 if (!consumeIf(Token::l_bracket))
1016 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001017
Chris Lattner2e595eb2018-07-10 10:08:27 -07001018 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001019 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1020}
1021
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001022/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001023ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001024 if (!consumeIf(Token::l_paren))
1025 return emitError("expected '(' at start of dimensional identifiers list");
1026
Chris Lattner2e595eb2018-07-10 10:08:27 -07001027 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001028 return parseCommaSeparatedList(Token::r_paren, parseElt);
1029}
1030
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001031/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001032///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001033/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1034/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1035/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001036///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001037/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1038// TODO(bondhugula): parse range size information.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001039AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001040 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001042 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001043
1044 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001045 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001047 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001048 }
1049 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001050 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001051 }
1052 if (!consumeIf(Token::l_paren)) {
1053 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001054 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001055 }
1056
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001057 SmallVector<AffineExpr *, 4> exprs;
1058 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001059 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001060 ParseResult res = elt ? ParseSuccess : ParseFailure;
1061 exprs.push_back(elt);
1062 return res;
1063 };
1064
1065 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001066 // affine expressions); the list cannot be empty.
1067 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1068 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001069 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001070
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001071 // Parse optional range sizes.
1072 // (`size` `(` dim-size (`,` dim-size)* `)`)?
1073 // TODO: check if sizes are non-negative whenever they are constant.
1074 SmallVector<AffineExpr *, 4> rangeSizes;
1075 if (consumeIf(Token::kw_size)) {
1076 // Location of the l_paren token (if it exists) for error reporting later.
1077 auto loc = getToken().getLoc();
1078 if (!consumeIf(Token::l_paren))
1079 return (emitError("expected '(' at start of affine map range"), nullptr);
1080
1081 auto parseRangeSize = [&]() -> ParseResult {
1082 auto *elt = parseAffineExpr();
1083 ParseResult res = elt ? ParseSuccess : ParseFailure;
1084 rangeSizes.push_back(elt);
1085 return res;
1086 };
1087
1088 setSymbolicParsing(true);
1089 if (parseCommaSeparatedList(Token::r_paren, parseRangeSize, false))
1090 return nullptr;
1091 if (exprs.size() > rangeSizes.size())
1092 return (emitError(loc, "fewer range sizes than range expressions"),
1093 nullptr);
1094 if (exprs.size() < rangeSizes.size())
1095 return (emitError(loc, "more range sizes than range expressions"),
1096 nullptr);
1097 }
1098
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001099 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001100 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001101}
1102
Chris Lattner2e595eb2018-07-10 10:08:27 -07001103AffineMap *Parser::parseAffineMapInline() {
1104 return AffineMapParser(state).parseAffineMapInline();
1105}
1106
MLIR Teamf85a6262018-06-27 11:03:08 -07001107//===----------------------------------------------------------------------===//
Chris Lattner78276e32018-07-07 15:48:26 -07001108// SSA
Chris Lattner4c95a502018-06-23 16:03:42 -07001109//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001110
Chris Lattner78276e32018-07-07 15:48:26 -07001111/// Parse a SSA operand for an instruction or statement.
1112///
1113/// ssa-use ::= ssa-id | ssa-constant
1114///
1115ParseResult Parser::parseSSAUse() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001116 if (getToken().is(Token::percent_identifier)) {
1117 StringRef name = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001118 consumeToken(Token::percent_identifier);
1119 // TODO: Return this use.
1120 (void)name;
1121 return ParseSuccess;
1122 }
1123
1124 // TODO: Parse SSA constants.
1125
1126 return emitError("expected SSA operand");
1127}
1128
1129/// Parse a (possibly empty) list of SSA operands.
1130///
1131/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1132/// ssa-use-list-opt ::= ssa-use-list?
1133///
1134ParseResult Parser::parseOptionalSSAUseList(Token::Kind endToken) {
1135 // TODO: Build and return this.
1136 return parseCommaSeparatedList(
1137 endToken, [&]() -> ParseResult { return parseSSAUse(); });
1138}
1139
1140/// Parse an SSA use with an associated type.
1141///
1142/// ssa-use-and-type ::= ssa-use `:` type
1143ParseResult Parser::parseSSAUseAndType() {
1144 if (parseSSAUse())
1145 return ParseFailure;
1146
1147 if (!consumeIf(Token::colon))
1148 return emitError("expected ':' and type for SSA operand");
1149
1150 if (!parseType())
1151 return ParseFailure;
1152
1153 return ParseSuccess;
1154}
1155
1156/// Parse a (possibly empty) list of SSA operands with types.
1157///
1158/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1159///
1160ParseResult Parser::parseOptionalSSAUseAndTypeList(Token::Kind endToken) {
1161 // TODO: Build and return this.
1162 return parseCommaSeparatedList(
1163 endToken, [&]() -> ParseResult { return parseSSAUseAndType(); });
1164}
1165
Chris Lattnere79379a2018-06-22 10:39:19 -07001166
Chris Lattner48af7d12018-07-09 19:05:38 -07001167//===----------------------------------------------------------------------===//
1168// CFG Functions
1169//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001170
Chris Lattner4c95a502018-06-23 16:03:42 -07001171namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001172/// This is a specialized parser for CFGFunction's, maintaining the state
1173/// transient to their bodies.
1174class CFGFunctionParser : public Parser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001175public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001176 CFGFunctionParser(ParserState &state, CFGFunction *function)
1177 : Parser(state), function(function), builder(function) {}
1178
1179 ParseResult parseFunctionBody();
1180
1181private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001182 CFGFunction *function;
1183 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001184
1185 /// This builder intentionally shadows the builder in the base class, with a
1186 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001187 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001188
Chris Lattner4c95a502018-06-23 16:03:42 -07001189 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001190 /// already exist. The location specified is the point of use, which allows
1191 /// us to diagnose references to blocks that are not defined precisely.
1192 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1193 auto &blockAndLoc = blocksByName[name];
1194 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001195 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001196 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001197 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001198 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001199 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001200
Chris Lattner48af7d12018-07-09 19:05:38 -07001201 ParseResult parseBasicBlock();
1202 OperationInst *parseCFGOperation();
1203 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001204};
1205} // end anonymous namespace
1206
Chris Lattner48af7d12018-07-09 19:05:38 -07001207ParseResult CFGFunctionParser::parseFunctionBody() {
1208 if (!consumeIf(Token::l_brace))
1209 return emitError("expected '{' in CFG function");
1210
1211 // Make sure we have at least one block.
1212 if (getToken().is(Token::r_brace))
1213 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001214
1215 // Parse the list of blocks.
1216 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001217 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001218 return ParseFailure;
1219
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001220 // Verify that all referenced blocks were defined. Iteration over a
1221 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001222 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001223 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001224 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001225 return emitError(elt.second.second,
1226 "reference to an undefined basic block '" +
1227 elt.first() + "'");
1228 }
1229
Chris Lattner48af7d12018-07-09 19:05:38 -07001230 getModule()->functionList.push_back(function);
Chris Lattner4c95a502018-06-23 16:03:42 -07001231 return ParseSuccess;
1232}
1233
1234/// Basic block declaration.
1235///
1236/// basic-block ::= bb-label instruction* terminator-stmt
1237/// bb-label ::= bb-id bb-arg-list? `:`
1238/// bb-id ::= bare-id
1239/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1240///
Chris Lattner48af7d12018-07-09 19:05:38 -07001241ParseResult CFGFunctionParser::parseBasicBlock() {
1242 SMLoc nameLoc = getToken().getLoc();
1243 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001244 if (!consumeIf(Token::bare_identifier))
1245 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001246
Chris Lattner48af7d12018-07-09 19:05:38 -07001247 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001248
1249 // If this block has already been parsed, then this is a redefinition with the
1250 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001251 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001252 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1253
Chris Lattner3a467cc2018-07-01 20:28:00 -07001254 // Add the block to the function.
Chris Lattner48af7d12018-07-09 19:05:38 -07001255 function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001256
Chris Lattner78276e32018-07-07 15:48:26 -07001257 // If an argument list is present, parse it.
1258 if (consumeIf(Token::l_paren)) {
1259 if (parseOptionalSSAUseAndTypeList(Token::r_paren))
1260 return ParseFailure;
1261
1262 // TODO: attach it.
1263 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001264
1265 if (!consumeIf(Token::colon))
1266 return emitError("expected ':' after basic block name");
1267
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001268 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001269 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001270
Chris Lattnered65a732018-06-28 20:45:33 -07001271 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001272 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
1273 auto loc = getToken().getLoc();
1274 auto *inst = parseCFGOperation();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001275 if (!inst)
Chris Lattnered65a732018-06-28 20:45:33 -07001276 return ParseFailure;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001277
Chris Lattner21e67f62018-07-06 10:46:19 -07001278 // We just parsed an operation. If it is a recognized one, verify that it
1279 // is structurally as we expect. If not, produce an error with a reasonable
1280 // source location.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001281 if (auto *opInfo = inst->getAbstractOperation(builder.getContext()))
Chris Lattner21e67f62018-07-06 10:46:19 -07001282 if (auto error = opInfo->verifyInvariants(inst))
1283 return emitError(loc, error);
Chris Lattnered65a732018-06-28 20:45:33 -07001284 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001285
Chris Lattner48af7d12018-07-09 19:05:38 -07001286 auto *term = parseTerminator();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001287 if (!term)
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001288 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001289
1290 return ParseSuccess;
1291}
1292
Chris Lattnered65a732018-06-28 20:45:33 -07001293/// Parse the CFG operation.
1294///
1295/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1296/// experiment that will eliminate "builtin" instructions as a thing.
1297///
1298/// cfg-operation ::=
1299/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1300/// `:` function-type
1301///
Chris Lattner48af7d12018-07-09 19:05:38 -07001302OperationInst *CFGFunctionParser::parseCFGOperation() {
Chris Lattner78276e32018-07-07 15:48:26 -07001303 StringRef resultID;
Chris Lattner48af7d12018-07-09 19:05:38 -07001304 if (getToken().is(Token::percent_identifier)) {
1305 resultID = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001306 consumeToken();
1307 if (!consumeIf(Token::equal))
1308 return (emitError("expected '=' after SSA name"), nullptr);
1309 }
Chris Lattnered65a732018-06-28 20:45:33 -07001310
Chris Lattner48af7d12018-07-09 19:05:38 -07001311 if (getToken().isNot(Token::string))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001312 return (emitError("expected operation name in quotes"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001313
Chris Lattner48af7d12018-07-09 19:05:38 -07001314 auto name = getToken().getStringValue();
Chris Lattnered65a732018-06-28 20:45:33 -07001315 if (name.empty())
Chris Lattner3a467cc2018-07-01 20:28:00 -07001316 return (emitError("empty operation name is invalid"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001317
1318 consumeToken(Token::string);
1319
1320 if (!consumeIf(Token::l_paren))
Chris Lattner7121b802018-07-04 20:45:39 -07001321 return (emitError("expected '(' to start operand list"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001322
Chris Lattner78276e32018-07-07 15:48:26 -07001323 // Parse the operand list.
1324 parseOptionalSSAUseList(Token::r_paren);
Chris Lattner7121b802018-07-04 20:45:39 -07001325
1326 SmallVector<NamedAttribute, 4> attributes;
Chris Lattner48af7d12018-07-09 19:05:38 -07001327 if (getToken().is(Token::l_brace)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001328 if (parseAttributeDict(attributes))
1329 return nullptr;
1330 }
Chris Lattnered65a732018-06-28 20:45:33 -07001331
Chris Lattner78276e32018-07-07 15:48:26 -07001332 // TODO: Don't drop result name and operand names on the floor.
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001333 auto nameId = builder.getIdentifier(name);
Chris Lattner48af7d12018-07-09 19:05:38 -07001334 return builder.createOperation(nameId, attributes);
Chris Lattnered65a732018-06-28 20:45:33 -07001335}
1336
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001337/// Parse the terminator instruction for a basic block.
1338///
1339/// terminator-stmt ::= `br` bb-id branch-use-list?
1340/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1341/// terminator-stmt ::=
1342/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1343/// terminator-stmt ::= `return` ssa-use-and-type-list?
1344///
Chris Lattner48af7d12018-07-09 19:05:38 -07001345TerminatorInst *CFGFunctionParser::parseTerminator() {
1346 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001347 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001348 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001349
1350 case Token::kw_return:
1351 consumeToken(Token::kw_return);
Chris Lattner48af7d12018-07-09 19:05:38 -07001352 return builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001353
1354 case Token::kw_br: {
1355 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001356 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001357 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001358 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001359 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001360 }
Chris Lattner78276e32018-07-07 15:48:26 -07001361 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001362 }
1363}
1364
Chris Lattner48af7d12018-07-09 19:05:38 -07001365//===----------------------------------------------------------------------===//
1366// ML Functions
1367//===----------------------------------------------------------------------===//
1368
1369namespace {
1370/// Refined parser for MLFunction bodies.
1371class MLFunctionParser : public Parser {
1372public:
1373 MLFunction *function;
1374
1375 /// This builder intentionally shadows the builder in the base class, with a
1376 /// more specific builder type.
1377 // TODO: MLFuncBuilder builder;
1378
1379 MLFunctionParser(ParserState &state, MLFunction *function)
1380 : Parser(state), function(function) {}
1381
1382 ParseResult parseFunctionBody();
1383 Statement *parseStatement(ParentType parent);
1384 ForStmt *parseForStmt(ParentType parent);
1385 IfStmt *parseIfStmt(ParentType parent);
1386 ParseResult parseNestedStatements(NodeStmt *parent);
1387};
1388} // end anonymous namespace
1389
Chris Lattner48af7d12018-07-09 19:05:38 -07001390ParseResult MLFunctionParser::parseFunctionBody() {
1391 if (!consumeIf(Token::l_brace))
1392 return emitError("expected '{' in ML function");
1393
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001394 // Make sure we have at least one statement.
Chris Lattner48af7d12018-07-09 19:05:38 -07001395 if (getToken().is(Token::r_brace))
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001396 return emitError("ML function must end with return statement");
1397
1398 // Parse the list of instructions.
1399 while (!consumeIf(Token::kw_return)) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001400 auto *stmt = parseStatement(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001401 if (!stmt)
1402 return ParseFailure;
1403 function->stmtList.push_back(stmt);
1404 }
1405
1406 // TODO: parse return statement operands
1407 if (!consumeIf(Token::r_brace))
1408 emitError("expected '}' in ML function");
1409
Chris Lattner48af7d12018-07-09 19:05:38 -07001410 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001411
1412 return ParseSuccess;
1413}
1414
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001415/// Statement.
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001416///
Chris Lattner48af7d12018-07-09 19:05:38 -07001417/// ml-stmt ::= instruction | ml-for-stmt | ml-if-stmt
1418///
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001419/// TODO: fix terminology in MLSpec document. ML functions
1420/// contain operation statements, not instructions.
1421///
Chris Lattner48af7d12018-07-09 19:05:38 -07001422Statement *MLFunctionParser::parseStatement(ParentType parent) {
1423 switch (getToken().getKind()) {
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001424 default:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001425 //TODO: parse OperationStmt
1426 return (emitError("expected statement"), nullptr);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001427
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001428 case Token::kw_for:
1429 return parseForStmt(parent);
1430
1431 case Token::kw_if:
1432 return parseIfStmt(parent);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001433 }
1434}
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001435
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001436/// For statement.
1437///
Chris Lattner48af7d12018-07-09 19:05:38 -07001438/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1439/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001440///
Chris Lattner48af7d12018-07-09 19:05:38 -07001441ForStmt *MLFunctionParser::parseForStmt(ParentType parent) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001442 consumeToken(Token::kw_for);
1443
1444 //TODO: parse loop header
1445 ForStmt *stmt = new ForStmt(parent);
1446 if (parseNestedStatements(stmt)) {
1447 delete stmt;
1448 return nullptr;
1449 }
1450 return stmt;
1451}
1452
1453/// If statement.
1454///
Chris Lattner48af7d12018-07-09 19:05:38 -07001455/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1456/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1457/// ml-if-stmt ::= ml-if-head
1458/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001459///
Chris Lattner48af7d12018-07-09 19:05:38 -07001460IfStmt *
1461MLFunctionParser::parseIfStmt(PointerUnion<MLFunction *, NodeStmt *> parent) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001462 consumeToken(Token::kw_if);
1463
1464 //TODO: parse condition
1465 IfStmt *stmt = new IfStmt(parent);
1466 if (parseNestedStatements(stmt)) {
1467 delete stmt;
1468 return nullptr;
1469 }
1470
1471 int clauseNum = 0;
1472 while (consumeIf(Token::kw_else)) {
1473 if (consumeIf(Token::kw_if)) {
1474 //TODO: parse condition
1475 }
1476 ElseClause * clause = new ElseClause(stmt, clauseNum);
1477 ++clauseNum;
1478 if (parseNestedStatements(clause)) {
1479 delete clause;
1480 return nullptr;
1481 }
1482 }
1483
1484 return stmt;
1485}
1486
1487///
1488/// Parse `{` ml-stmt* `}`
1489///
Chris Lattner48af7d12018-07-09 19:05:38 -07001490ParseResult MLFunctionParser::parseNestedStatements(NodeStmt *parent) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001491 if (!consumeIf(Token::l_brace))
1492 return emitError("expected '{' before statement list");
1493
1494 if (consumeIf(Token::r_brace)) {
1495 // TODO: parse OperationStmt
1496 return ParseSuccess;
1497 }
1498
1499 while (!consumeIf(Token::r_brace)) {
1500 auto *stmt = parseStatement(parent);
1501 if (!stmt)
1502 return ParseFailure;
1503 parent->children.push_back(stmt);
1504 }
1505
1506 return ParseSuccess;
1507}
1508
Chris Lattner4c95a502018-06-23 16:03:42 -07001509//===----------------------------------------------------------------------===//
1510// Top-level entity parsing.
1511//===----------------------------------------------------------------------===//
1512
Chris Lattner2e595eb2018-07-10 10:08:27 -07001513namespace {
1514/// This parser handles entities that are only valid at the top level of the
1515/// file.
1516class ModuleParser : public Parser {
1517public:
1518 explicit ModuleParser(ParserState &state) : Parser(state) {}
1519
1520 ParseResult parseModule();
1521
1522private:
1523 ParseResult parseAffineMapDef();
1524
1525 // Functions.
1526 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type);
1527 ParseResult parseExtFunc();
1528 ParseResult parseCFGFunc();
1529 ParseResult parseMLFunc();
1530};
1531} // end anonymous namespace
1532
1533/// Affine map declaration.
1534///
1535/// affine-map-def ::= affine-map-id `=` affine-map-inline
1536///
1537ParseResult ModuleParser::parseAffineMapDef() {
1538 assert(getToken().is(Token::hash_identifier));
1539
1540 StringRef affineMapId = getTokenSpelling().drop_front();
1541
1542 // Check for redefinitions.
1543 auto *&entry = getState().affineMapDefinitions[affineMapId];
1544 if (entry)
1545 return emitError("redefinition of affine map id '" + affineMapId + "'");
1546
1547 consumeToken(Token::hash_identifier);
1548
1549 // Parse the '='
1550 if (!consumeIf(Token::equal))
1551 return emitError("expected '=' in affine map outlined definition");
1552
1553 entry = parseAffineMapInline();
1554 if (!entry)
1555 return ParseFailure;
1556
1557 getModule()->affineMapList.push_back(entry);
1558 return ParseSuccess;
1559}
1560
1561/// Parse a function signature, starting with a name and including the parameter
1562/// list.
1563///
1564/// argument-list ::= type (`,` type)* | /*empty*/
1565/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1566///
1567ParseResult ModuleParser::parseFunctionSignature(StringRef &name,
1568 FunctionType *&type) {
1569 if (getToken().isNot(Token::at_identifier))
1570 return emitError("expected a function identifier like '@foo'");
1571
1572 name = getTokenSpelling().drop_front();
1573 consumeToken(Token::at_identifier);
1574
1575 if (getToken().isNot(Token::l_paren))
1576 return emitError("expected '(' in function signature");
1577
1578 SmallVector<Type *, 4> arguments;
1579 if (parseTypeList(arguments))
1580 return ParseFailure;
1581
1582 // Parse the return type if present.
1583 SmallVector<Type *, 4> results;
1584 if (consumeIf(Token::arrow)) {
1585 if (parseTypeList(results))
1586 return ParseFailure;
1587 }
1588 type = builder.getFunctionType(arguments, results);
1589 return ParseSuccess;
1590}
1591
1592/// External function declarations.
1593///
1594/// ext-func ::= `extfunc` function-signature
1595///
1596ParseResult ModuleParser::parseExtFunc() {
1597 consumeToken(Token::kw_extfunc);
1598
1599 StringRef name;
1600 FunctionType *type = nullptr;
1601 if (parseFunctionSignature(name, type))
1602 return ParseFailure;
1603
1604 // Okay, the external function definition was parsed correctly.
1605 getModule()->functionList.push_back(new ExtFunction(name, type));
1606 return ParseSuccess;
1607}
1608
1609/// CFG function declarations.
1610///
1611/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
1612///
1613ParseResult ModuleParser::parseCFGFunc() {
1614 consumeToken(Token::kw_cfgfunc);
1615
1616 StringRef name;
1617 FunctionType *type = nullptr;
1618 if (parseFunctionSignature(name, type))
1619 return ParseFailure;
1620
1621 // Okay, the CFG function signature was parsed correctly, create the function.
1622 auto function = new CFGFunction(name, type);
1623
1624 return CFGFunctionParser(getState(), function).parseFunctionBody();
1625}
1626
1627/// ML function declarations.
1628///
1629/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
1630///
1631ParseResult ModuleParser::parseMLFunc() {
1632 consumeToken(Token::kw_mlfunc);
1633
1634 StringRef name;
1635 FunctionType *type = nullptr;
1636
1637 // FIXME: Parse ML function signature (args + types)
1638 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
1639 if (parseFunctionSignature(name, type))
1640 return ParseFailure;
1641
1642 // Okay, the ML function signature was parsed correctly, create the function.
1643 auto function = new MLFunction(name, type);
1644
1645 return MLFunctionParser(getState(), function).parseFunctionBody();
1646}
1647
Chris Lattnere79379a2018-06-22 10:39:19 -07001648/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001649ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07001650 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001651 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07001652 default:
1653 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001654 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001655
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001656 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07001657 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001658 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07001659
1660 // If we got an error token, then the lexer already emitted an error, just
1661 // stop. Someday we could introduce error recovery if there was demand for
1662 // it.
1663 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001664 return ParseFailure;
1665
1666 case Token::hash_identifier:
1667 if (parseAffineMapDef())
1668 return ParseFailure;
1669 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07001670
1671 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001672 if (parseExtFunc())
1673 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001674 break;
1675
Chris Lattner4c95a502018-06-23 16:03:42 -07001676 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001677 if (parseCFGFunc())
1678 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07001679 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07001680
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001681 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001682 if (parseMLFunc())
1683 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001684 break;
1685
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001686 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07001687 }
1688 }
1689}
1690
1691//===----------------------------------------------------------------------===//
1692
Jacques Pienaar7b829702018-07-03 13:24:09 -07001693void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
1694 const auto &sourceMgr = *error.getSourceMgr();
1695 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
1696}
1697
Chris Lattnere79379a2018-06-22 10:39:19 -07001698/// This parses the file specified by the indicated SourceMgr and returns an
1699/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07001700Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07001701 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001702 // This is the result module we are parsing into.
1703 std::unique_ptr<Module> module(new Module(context));
1704
1705 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07001706 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001707 if (ModuleParser(state).parseModule())
1708 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07001709
1710 // Make sure the parse module has no other structural problems detected by the
1711 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001712 module->verify();
1713 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07001714}