MLIR  20.0.0git
LocationParser.cpp
Go to the documentation of this file.
1 //===- LocationParser.cpp - MLIR Location Parser -------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Parser.h"
10 #include "Token.h"
11 #include "mlir/IR/Attributes.h"
13 #include "mlir/IR/Location.h"
14 #include "mlir/Support/LLVM.h"
15 #include <optional>
16 
17 using namespace mlir;
18 using namespace mlir::detail;
19 
20 /// Specific location instances.
21 ///
22 /// location-inst ::= filelinecol-location |
23 /// name-location |
24 /// callsite-location |
25 /// fused-location |
26 /// unknown-location
27 /// filelinecol-location ::= string-literal ':' integer-literal
28 /// ':' integer-literal
29 /// name-location ::= string-literal
30 /// callsite-location ::= 'callsite' '(' location-inst 'at' location-inst ')'
31 /// fused-location ::= fused ('<' attribute-value '>')?
32 /// '[' location-inst (location-inst ',')* ']'
33 /// unknown-location ::= 'unknown'
34 ///
36  consumeToken(Token::bare_identifier);
37 
38  // Parse the '('.
39  if (parseToken(Token::l_paren, "expected '(' in callsite location"))
40  return failure();
41 
42  // Parse the callee location.
43  LocationAttr calleeLoc;
44  if (parseLocationInstance(calleeLoc))
45  return failure();
46 
47  // Parse the 'at'.
48  if (getToken().isNot(Token::bare_identifier) ||
49  getToken().getSpelling() != "at")
50  return emitWrongTokenError("expected 'at' in callsite location");
51  consumeToken(Token::bare_identifier);
52 
53  // Parse the caller location.
54  LocationAttr callerLoc;
55  if (parseLocationInstance(callerLoc))
56  return failure();
57 
58  // Parse the ')'.
59  if (parseToken(Token::r_paren, "expected ')' in callsite location"))
60  return failure();
61 
62  // Return the callsite location.
63  loc = CallSiteLoc::get(calleeLoc, callerLoc);
64  return success();
65 }
66 
68  consumeToken(Token::bare_identifier);
69 
70  // Try to parse the optional metadata.
71  Attribute metadata;
72  if (consumeIf(Token::less)) {
73  metadata = parseAttribute();
74  if (!metadata)
75  return failure();
76 
77  // Parse the '>' token.
78  if (parseToken(Token::greater,
79  "expected '>' after fused location metadata"))
80  return failure();
81  }
82 
83  SmallVector<Location, 4> locations;
84  auto parseElt = [&] {
85  LocationAttr newLoc;
86  if (parseLocationInstance(newLoc))
87  return failure();
88  locations.push_back(newLoc);
89  return success();
90  };
91 
93  " in fused location"))
94  return failure();
95 
96  // Return the fused location.
97  loc = FusedLoc::get(locations, metadata, getContext());
98  return success();
99 }
100 
102  auto *ctx = getContext();
103  auto str = getToken().getStringValue();
104  consumeToken(Token::string);
105 
106  std::optional<unsigned> startLine, startColumn, endLine, endColumn;
107 
108  // If the next token is ':' this is a filelinecol location.
109  if (consumeIf(Token::colon)) {
110  // Parse the line number.
111  if (getToken().isNot(Token::integer))
112  return emitWrongTokenError(
113  "expected integer line number in FileLineColRange");
114  startLine = getToken().getUnsignedIntegerValue();
115  if (!startLine)
116  return emitWrongTokenError(
117  "expected integer line number in FileLineColRange");
118  consumeToken(Token::integer);
119 
120  // Parse the ':'.
121  if (getToken().isNot(Token::colon)) {
122  loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine);
123  return success();
124  }
125  consumeToken(Token::colon);
126 
127  // Parse the column number.
128  if (getToken().isNot(Token::integer)) {
129  return emitWrongTokenError(
130  "expected integer column number in FileLineColRange");
131  }
132  startColumn = getToken().getUnsignedIntegerValue();
133  if (!startColumn.has_value())
134  return emitError("expected integer column number in FileLineColRange");
135  consumeToken(Token::integer);
136 
137  if (!isCurrentTokenAKeyword() || getTokenSpelling() != "to") {
138  loc = FileLineColLoc::get(ctx, str, *startLine, *startColumn);
139  return success();
140  }
141  consumeToken();
142 
143  // Parse the line number.
144  if (getToken().is(Token::integer)) {
145  endLine = getToken().getUnsignedIntegerValue();
146  if (!endLine) {
147  return emitWrongTokenError(
148  "expected integer line number in FileLineColRange");
149  }
150  consumeToken(Token::integer);
151  }
152 
153  // Parse the ':'.
154  if (getToken().isNot(Token::colon)) {
155  return emitWrongTokenError(
156  "expected either integer or `:` post `to` in FileLineColRange");
157  }
158  consumeToken(Token::colon);
159 
160  // Parse the column number.
161  if (getToken().isNot(Token::integer)) {
162  return emitWrongTokenError(
163  "expected integer column number in FileLineColRange");
164  }
165  endColumn = getToken().getUnsignedIntegerValue();
166  if (!endColumn.has_value())
167  return emitError("expected integer column number in FileLineColRange");
168  consumeToken(Token::integer);
169 
170  if (endLine.has_value()) {
171  loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine,
172  *startColumn, *endLine, *endColumn);
173  } else {
174  loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine,
175  *startColumn, *endColumn);
176  }
177  return success();
178  }
179 
180  // Otherwise, this is a NameLoc.
181 
182  // Check for a child location.
183  if (consumeIf(Token::l_paren)) {
184  // Parse the child location.
185  LocationAttr childLoc;
186  if (parseLocationInstance(childLoc))
187  return failure();
188 
189  loc = NameLoc::get(StringAttr::get(ctx, str), childLoc);
190 
191  // Parse the closing ')'.
192  if (parseToken(Token::r_paren,
193  "expected ')' after child location of NameLoc"))
194  return failure();
195  } else {
196  loc = NameLoc::get(StringAttr::get(ctx, str));
197  }
198 
199  return success();
200 }
201 
203  // Handle aliases.
204  if (getToken().is(Token::hash_identifier)) {
205  Attribute locAttr = parseExtendedAttr(Type());
206  if (!locAttr)
207  return failure();
208  if (!(loc = dyn_cast<LocationAttr>(locAttr)))
209  return emitError("expected location attribute, but got") << locAttr;
210  return success();
211  }
212 
213  // Handle either name or filelinecol locations.
214  if (getToken().is(Token::string))
215  return parseNameOrFileLineColRange(loc);
216 
217  // Bare tokens required for other cases.
218  if (!getToken().is(Token::bare_identifier))
219  return emitWrongTokenError("expected location instance");
220 
221  // Check for the 'callsite' signifying a callsite location.
222  if (getToken().getSpelling() == "callsite")
223  return parseCallSiteLocation(loc);
224 
225  // If the token is 'fused', then this is a fused location.
226  if (getToken().getSpelling() == "fused")
227  return parseFusedLocation(loc);
228 
229  // Check for a 'unknown' for an unknown location.
230  if (getToken().getSpelling() == "unknown") {
231  consumeToken(Token::bare_identifier);
232  loc = UnknownLoc::get(getContext());
233  return success();
234  }
235 
236  return emitWrongTokenError("expected location instance");
237 }
@ Square
Square brackets surrounding zero or more operands.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
Definition: Location.cpp:160
Location objects represent source locations information in MLIR.
Definition: Location.h:31
std::string getStringValue() const
Given a token containing a string literal, return its value, including removing the quote characters ...
Definition: Token.cpp:86
std::optional< unsigned > getUnsignedIntegerValue() const
For an integer token, return its value as an unsigned.
Definition: Token.cpp:34
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
ParseResult parseToken(Token::Kind expectedToken, const Twine &message)
Consume the specified token if present and return success.
Definition: Parser.cpp:267
InFlightDiagnostic emitError(const Twine &message={})
Emit an error and return failure.
Definition: Parser.cpp:192
Attribute parseAttribute(Type type={})
Parse an arbitrary attribute with an optional type.
StringRef getTokenSpelling() const
Definition: Parser.h:104
ParseResult parseLocationInstance(LocationAttr &loc)
Parse a raw location instance.
void consumeToken()
Advance the current lexer onto the next token.
Definition: Parser.h:119
MLIRContext * getContext() const
Definition: Parser.h:38
InFlightDiagnostic emitWrongTokenError(const Twine &message={})
Emit an error about a "wrong token".
Definition: Parser.cpp:215
ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())
Parse a list of comma-separated items with an optional delimiter.
Definition: Parser.cpp:84
ParseResult parseNameOrFileLineColRange(LocationAttr &loc)
Parse a name or FileLineCol location instance.
ParseResult parseFusedLocation(LocationAttr &loc)
Parse a fused location instance.
bool isCurrentTokenAKeyword() const
Returns true if the current token corresponds to a keyword.
Definition: Parser.h:166
ParseResult parseCallSiteLocation(LocationAttr &loc)
Parse a callsite location instance.
Attribute parseExtendedAttr(Type type)
Parse an extended attribute.
const Token & getToken() const
Return the current token the parser is inspecting.
Definition: Parser.h:103
bool consumeIf(Token::Kind kind)
If the current token has the specified kind, consume it and return true.
Definition: Parser.h:111
AttrTypeReplacer.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...