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"
15 #include "mlir/Support/LogicalResult.h"
18 using namespace mlir::detail
;
20 /// Specific location instances.
22 /// location-inst ::= filelinecol-location |
24 /// callsite-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'
35 ParseResult
Parser::parseCallSiteLocation(LocationAttr
&loc
) {
36 consumeToken(Token::bare_identifier
);
39 if (parseToken(Token::l_paren
, "expected '(' in callsite location"))
42 // Parse the callee location.
43 LocationAttr calleeLoc
;
44 if (parseLocationInstance(calleeLoc
))
48 if (getToken().isNot(Token::bare_identifier
) ||
49 getToken().getSpelling() != "at")
50 return emitWrongTokenError("expected 'at' in callsite location");
51 consumeToken(Token::bare_identifier
);
53 // Parse the caller location.
54 LocationAttr callerLoc
;
55 if (parseLocationInstance(callerLoc
))
59 if (parseToken(Token::r_paren
, "expected ')' in callsite location"))
62 // Return the callsite location.
63 loc
= CallSiteLoc::get(calleeLoc
, callerLoc
);
67 ParseResult
Parser::parseFusedLocation(LocationAttr
&loc
) {
68 consumeToken(Token::bare_identifier
);
70 // Try to parse the optional metadata.
72 if (consumeIf(Token::less
)) {
73 metadata
= parseAttribute();
77 // Parse the '>' token.
78 if (parseToken(Token::greater
,
79 "expected '>' after fused location metadata"))
83 SmallVector
<Location
, 4> locations
;
86 if (parseLocationInstance(newLoc
))
88 locations
.push_back(newLoc
);
92 if (parseCommaSeparatedList(Delimiter::Square
, parseElt
,
93 " in fused location"))
96 // Return the fused location.
97 loc
= FusedLoc::get(locations
, metadata
, getContext());
101 ParseResult
Parser::parseNameOrFileLineColLocation(LocationAttr
&loc
) {
102 auto *ctx
= getContext();
103 auto str
= getToken().getStringValue();
104 consumeToken(Token::string
);
106 // If the next token is ':' this is a filelinecol location.
107 if (consumeIf(Token::colon
)) {
108 // Parse the line number.
109 if (getToken().isNot(Token::integer
))
110 return emitWrongTokenError(
111 "expected integer line number in FileLineColLoc");
112 auto line
= getToken().getUnsignedIntegerValue();
114 return emitWrongTokenError(
115 "expected integer line number in FileLineColLoc");
116 consumeToken(Token::integer
);
119 if (parseToken(Token::colon
, "expected ':' in FileLineColLoc"))
122 // Parse the column number.
123 if (getToken().isNot(Token::integer
))
124 return emitWrongTokenError(
125 "expected integer column number in FileLineColLoc");
126 auto column
= getToken().getUnsignedIntegerValue();
127 if (!column
.has_value())
128 return emitError("expected integer column number in FileLineColLoc");
129 consumeToken(Token::integer
);
131 loc
= FileLineColLoc::get(ctx
, str
, *line
, *column
);
135 // Otherwise, this is a NameLoc.
137 // Check for a child location.
138 if (consumeIf(Token::l_paren
)) {
139 // Parse the child location.
140 LocationAttr childLoc
;
141 if (parseLocationInstance(childLoc
))
144 loc
= NameLoc::get(StringAttr::get(ctx
, str
), childLoc
);
146 // Parse the closing ')'.
147 if (parseToken(Token::r_paren
,
148 "expected ')' after child location of NameLoc"))
151 loc
= NameLoc::get(StringAttr::get(ctx
, str
));
157 ParseResult
Parser::parseLocationInstance(LocationAttr
&loc
) {
159 if (getToken().is(Token::hash_identifier
)) {
160 Attribute locAttr
= parseExtendedAttr(Type());
163 if (!(loc
= dyn_cast
<LocationAttr
>(locAttr
)))
164 return emitError("expected location attribute, but got") << locAttr
;
168 // Handle either name or filelinecol locations.
169 if (getToken().is(Token::string
))
170 return parseNameOrFileLineColLocation(loc
);
172 // Bare tokens required for other cases.
173 if (!getToken().is(Token::bare_identifier
))
174 return emitWrongTokenError("expected location instance");
176 // Check for the 'callsite' signifying a callsite location.
177 if (getToken().getSpelling() == "callsite")
178 return parseCallSiteLocation(loc
);
180 // If the token is 'fused', then this is a fused location.
181 if (getToken().getSpelling() == "fused")
182 return parseFusedLocation(loc
);
184 // Check for a 'unknown' for an unknown location.
185 if (getToken().getSpelling() == "unknown") {
186 consumeToken(Token::bare_identifier
);
187 loc
= UnknownLoc::get(getContext());
191 return emitWrongTokenError("expected location instance");