1 //===- LocationParser.cpp - MLIR Location Parser -------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "mlir/IR/Attributes.h"
12 #include "mlir/IR/BuiltinAttributes.h"
13 #include "mlir/IR/Location.h"
14 #include "mlir/Support/LLVM.h"
17 using namespace mlir::detail
;
19 /// Specific location instances.
21 /// location-inst ::= filelinecol-location |
23 /// callsite-location |
26 /// filelinecol-location ::= string-literal ':' integer-literal
27 /// ':' integer-literal
28 /// name-location ::= string-literal
29 /// callsite-location ::= 'callsite' '(' location-inst 'at' location-inst ')'
30 /// fused-location ::= fused ('<' attribute-value '>')?
31 /// '[' location-inst (location-inst ',')* ']'
32 /// unknown-location ::= 'unknown'
34 ParseResult
Parser::parseCallSiteLocation(LocationAttr
&loc
) {
35 consumeToken(Token::bare_identifier
);
38 if (parseToken(Token::l_paren
, "expected '(' in callsite location"))
41 // Parse the callee location.
42 LocationAttr calleeLoc
;
43 if (parseLocationInstance(calleeLoc
))
47 if (getToken().isNot(Token::bare_identifier
) ||
48 getToken().getSpelling() != "at")
49 return emitWrongTokenError("expected 'at' in callsite location");
50 consumeToken(Token::bare_identifier
);
52 // Parse the caller location.
53 LocationAttr callerLoc
;
54 if (parseLocationInstance(callerLoc
))
58 if (parseToken(Token::r_paren
, "expected ')' in callsite location"))
61 // Return the callsite location.
62 loc
= CallSiteLoc::get(calleeLoc
, callerLoc
);
66 ParseResult
Parser::parseFusedLocation(LocationAttr
&loc
) {
67 consumeToken(Token::bare_identifier
);
69 // Try to parse the optional metadata.
71 if (consumeIf(Token::less
)) {
72 metadata
= parseAttribute();
76 // Parse the '>' token.
77 if (parseToken(Token::greater
,
78 "expected '>' after fused location metadata"))
82 SmallVector
<Location
, 4> locations
;
85 if (parseLocationInstance(newLoc
))
87 locations
.push_back(newLoc
);
91 if (parseCommaSeparatedList(Delimiter::Square
, parseElt
,
92 " in fused location"))
95 // Return the fused location.
96 loc
= FusedLoc::get(locations
, metadata
, getContext());
100 ParseResult
Parser::parseNameOrFileLineColLocation(LocationAttr
&loc
) {
101 auto *ctx
= getContext();
102 auto str
= getToken().getStringValue();
103 consumeToken(Token::string
);
105 // If the next token is ':' this is a filelinecol location.
106 if (consumeIf(Token::colon
)) {
107 // Parse the line number.
108 if (getToken().isNot(Token::integer
))
109 return emitWrongTokenError(
110 "expected integer line number in FileLineColLoc");
111 auto line
= getToken().getUnsignedIntegerValue();
113 return emitWrongTokenError(
114 "expected integer line number in FileLineColLoc");
115 consumeToken(Token::integer
);
118 if (parseToken(Token::colon
, "expected ':' in FileLineColLoc"))
121 // Parse the column number.
122 if (getToken().isNot(Token::integer
))
123 return emitWrongTokenError(
124 "expected integer column number in FileLineColLoc");
125 auto column
= getToken().getUnsignedIntegerValue();
126 if (!column
.has_value())
127 return emitError("expected integer column number in FileLineColLoc");
128 consumeToken(Token::integer
);
130 loc
= FileLineColLoc::get(ctx
, str
, *line
, *column
);
134 // Otherwise, this is a NameLoc.
136 // Check for a child location.
137 if (consumeIf(Token::l_paren
)) {
138 // Parse the child location.
139 LocationAttr childLoc
;
140 if (parseLocationInstance(childLoc
))
143 loc
= NameLoc::get(StringAttr::get(ctx
, str
), childLoc
);
145 // Parse the closing ')'.
146 if (parseToken(Token::r_paren
,
147 "expected ')' after child location of NameLoc"))
150 loc
= NameLoc::get(StringAttr::get(ctx
, str
));
156 ParseResult
Parser::parseLocationInstance(LocationAttr
&loc
) {
158 if (getToken().is(Token::hash_identifier
)) {
159 Attribute locAttr
= parseExtendedAttr(Type());
162 if (!(loc
= dyn_cast
<LocationAttr
>(locAttr
)))
163 return emitError("expected location attribute, but got") << locAttr
;
167 // Handle either name or filelinecol locations.
168 if (getToken().is(Token::string
))
169 return parseNameOrFileLineColLocation(loc
);
171 // Bare tokens required for other cases.
172 if (!getToken().is(Token::bare_identifier
))
173 return emitWrongTokenError("expected location instance");
175 // Check for the 'callsite' signifying a callsite location.
176 if (getToken().getSpelling() == "callsite")
177 return parseCallSiteLocation(loc
);
179 // If the token is 'fused', then this is a fused location.
180 if (getToken().getSpelling() == "fused")
181 return parseFusedLocation(loc
);
183 // Check for a 'unknown' for an unknown location.
184 if (getToken().getSpelling() == "unknown") {
185 consumeToken(Token::bare_identifier
);
186 loc
= UnknownLoc::get(getContext());
190 return emitWrongTokenError("expected location instance");