1*c60b897dSRiver Riddle //===- LocationParser.cpp - MLIR Location Parser -------------------------===//
2*c60b897dSRiver Riddle //
3*c60b897dSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c60b897dSRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
5*c60b897dSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c60b897dSRiver Riddle //
7*c60b897dSRiver Riddle //===----------------------------------------------------------------------===//
8*c60b897dSRiver Riddle
9*c60b897dSRiver Riddle #include "Parser.h"
10*c60b897dSRiver Riddle
11*c60b897dSRiver Riddle using namespace mlir;
12*c60b897dSRiver Riddle using namespace mlir::detail;
13*c60b897dSRiver Riddle
14*c60b897dSRiver Riddle /// Specific location instances.
15*c60b897dSRiver Riddle ///
16*c60b897dSRiver Riddle /// location-inst ::= filelinecol-location |
17*c60b897dSRiver Riddle /// name-location |
18*c60b897dSRiver Riddle /// callsite-location |
19*c60b897dSRiver Riddle /// fused-location |
20*c60b897dSRiver Riddle /// unknown-location
21*c60b897dSRiver Riddle /// filelinecol-location ::= string-literal ':' integer-literal
22*c60b897dSRiver Riddle /// ':' integer-literal
23*c60b897dSRiver Riddle /// name-location ::= string-literal
24*c60b897dSRiver Riddle /// callsite-location ::= 'callsite' '(' location-inst 'at' location-inst ')'
25*c60b897dSRiver Riddle /// fused-location ::= fused ('<' attribute-value '>')?
26*c60b897dSRiver Riddle /// '[' location-inst (location-inst ',')* ']'
27*c60b897dSRiver Riddle /// unknown-location ::= 'unknown'
28*c60b897dSRiver Riddle ///
parseCallSiteLocation(LocationAttr & loc)29*c60b897dSRiver Riddle ParseResult Parser::parseCallSiteLocation(LocationAttr &loc) {
30*c60b897dSRiver Riddle consumeToken(Token::bare_identifier);
31*c60b897dSRiver Riddle
32*c60b897dSRiver Riddle // Parse the '('.
33*c60b897dSRiver Riddle if (parseToken(Token::l_paren, "expected '(' in callsite location"))
34*c60b897dSRiver Riddle return failure();
35*c60b897dSRiver Riddle
36*c60b897dSRiver Riddle // Parse the callee location.
37*c60b897dSRiver Riddle LocationAttr calleeLoc;
38*c60b897dSRiver Riddle if (parseLocationInstance(calleeLoc))
39*c60b897dSRiver Riddle return failure();
40*c60b897dSRiver Riddle
41*c60b897dSRiver Riddle // Parse the 'at'.
42*c60b897dSRiver Riddle if (getToken().isNot(Token::bare_identifier) ||
43*c60b897dSRiver Riddle getToken().getSpelling() != "at")
44*c60b897dSRiver Riddle return emitWrongTokenError("expected 'at' in callsite location");
45*c60b897dSRiver Riddle consumeToken(Token::bare_identifier);
46*c60b897dSRiver Riddle
47*c60b897dSRiver Riddle // Parse the caller location.
48*c60b897dSRiver Riddle LocationAttr callerLoc;
49*c60b897dSRiver Riddle if (parseLocationInstance(callerLoc))
50*c60b897dSRiver Riddle return failure();
51*c60b897dSRiver Riddle
52*c60b897dSRiver Riddle // Parse the ')'.
53*c60b897dSRiver Riddle if (parseToken(Token::r_paren, "expected ')' in callsite location"))
54*c60b897dSRiver Riddle return failure();
55*c60b897dSRiver Riddle
56*c60b897dSRiver Riddle // Return the callsite location.
57*c60b897dSRiver Riddle loc = CallSiteLoc::get(calleeLoc, callerLoc);
58*c60b897dSRiver Riddle return success();
59*c60b897dSRiver Riddle }
60*c60b897dSRiver Riddle
parseFusedLocation(LocationAttr & loc)61*c60b897dSRiver Riddle ParseResult Parser::parseFusedLocation(LocationAttr &loc) {
62*c60b897dSRiver Riddle consumeToken(Token::bare_identifier);
63*c60b897dSRiver Riddle
64*c60b897dSRiver Riddle // Try to parse the optional metadata.
65*c60b897dSRiver Riddle Attribute metadata;
66*c60b897dSRiver Riddle if (consumeIf(Token::less)) {
67*c60b897dSRiver Riddle metadata = parseAttribute();
68*c60b897dSRiver Riddle if (!metadata)
69*c60b897dSRiver Riddle return failure();
70*c60b897dSRiver Riddle
71*c60b897dSRiver Riddle // Parse the '>' token.
72*c60b897dSRiver Riddle if (parseToken(Token::greater,
73*c60b897dSRiver Riddle "expected '>' after fused location metadata"))
74*c60b897dSRiver Riddle return failure();
75*c60b897dSRiver Riddle }
76*c60b897dSRiver Riddle
77*c60b897dSRiver Riddle SmallVector<Location, 4> locations;
78*c60b897dSRiver Riddle auto parseElt = [&] {
79*c60b897dSRiver Riddle LocationAttr newLoc;
80*c60b897dSRiver Riddle if (parseLocationInstance(newLoc))
81*c60b897dSRiver Riddle return failure();
82*c60b897dSRiver Riddle locations.push_back(newLoc);
83*c60b897dSRiver Riddle return success();
84*c60b897dSRiver Riddle };
85*c60b897dSRiver Riddle
86*c60b897dSRiver Riddle if (parseCommaSeparatedList(Delimiter::Square, parseElt,
87*c60b897dSRiver Riddle " in fused location"))
88*c60b897dSRiver Riddle return failure();
89*c60b897dSRiver Riddle
90*c60b897dSRiver Riddle // Return the fused location.
91*c60b897dSRiver Riddle loc = FusedLoc::get(locations, metadata, getContext());
92*c60b897dSRiver Riddle return success();
93*c60b897dSRiver Riddle }
94*c60b897dSRiver Riddle
parseNameOrFileLineColLocation(LocationAttr & loc)95*c60b897dSRiver Riddle ParseResult Parser::parseNameOrFileLineColLocation(LocationAttr &loc) {
96*c60b897dSRiver Riddle auto *ctx = getContext();
97*c60b897dSRiver Riddle auto str = getToken().getStringValue();
98*c60b897dSRiver Riddle consumeToken(Token::string);
99*c60b897dSRiver Riddle
100*c60b897dSRiver Riddle // If the next token is ':' this is a filelinecol location.
101*c60b897dSRiver Riddle if (consumeIf(Token::colon)) {
102*c60b897dSRiver Riddle // Parse the line number.
103*c60b897dSRiver Riddle if (getToken().isNot(Token::integer))
104*c60b897dSRiver Riddle return emitWrongTokenError(
105*c60b897dSRiver Riddle "expected integer line number in FileLineColLoc");
106*c60b897dSRiver Riddle auto line = getToken().getUnsignedIntegerValue();
107*c60b897dSRiver Riddle if (!line)
108*c60b897dSRiver Riddle return emitWrongTokenError(
109*c60b897dSRiver Riddle "expected integer line number in FileLineColLoc");
110*c60b897dSRiver Riddle consumeToken(Token::integer);
111*c60b897dSRiver Riddle
112*c60b897dSRiver Riddle // Parse the ':'.
113*c60b897dSRiver Riddle if (parseToken(Token::colon, "expected ':' in FileLineColLoc"))
114*c60b897dSRiver Riddle return failure();
115*c60b897dSRiver Riddle
116*c60b897dSRiver Riddle // Parse the column number.
117*c60b897dSRiver Riddle if (getToken().isNot(Token::integer))
118*c60b897dSRiver Riddle return emitWrongTokenError(
119*c60b897dSRiver Riddle "expected integer column number in FileLineColLoc");
120*c60b897dSRiver Riddle auto column = getToken().getUnsignedIntegerValue();
121*c60b897dSRiver Riddle if (!column.has_value())
122*c60b897dSRiver Riddle return emitError("expected integer column number in FileLineColLoc");
123*c60b897dSRiver Riddle consumeToken(Token::integer);
124*c60b897dSRiver Riddle
125*c60b897dSRiver Riddle loc = FileLineColLoc::get(ctx, str, line.value(), column.value());
126*c60b897dSRiver Riddle return success();
127*c60b897dSRiver Riddle }
128*c60b897dSRiver Riddle
129*c60b897dSRiver Riddle // Otherwise, this is a NameLoc.
130*c60b897dSRiver Riddle
131*c60b897dSRiver Riddle // Check for a child location.
132*c60b897dSRiver Riddle if (consumeIf(Token::l_paren)) {
133*c60b897dSRiver Riddle // Parse the child location.
134*c60b897dSRiver Riddle LocationAttr childLoc;
135*c60b897dSRiver Riddle if (parseLocationInstance(childLoc))
136*c60b897dSRiver Riddle return failure();
137*c60b897dSRiver Riddle
138*c60b897dSRiver Riddle loc = NameLoc::get(StringAttr::get(ctx, str), childLoc);
139*c60b897dSRiver Riddle
140*c60b897dSRiver Riddle // Parse the closing ')'.
141*c60b897dSRiver Riddle if (parseToken(Token::r_paren,
142*c60b897dSRiver Riddle "expected ')' after child location of NameLoc"))
143*c60b897dSRiver Riddle return failure();
144*c60b897dSRiver Riddle } else {
145*c60b897dSRiver Riddle loc = NameLoc::get(StringAttr::get(ctx, str));
146*c60b897dSRiver Riddle }
147*c60b897dSRiver Riddle
148*c60b897dSRiver Riddle return success();
149*c60b897dSRiver Riddle }
150*c60b897dSRiver Riddle
parseLocationInstance(LocationAttr & loc)151*c60b897dSRiver Riddle ParseResult Parser::parseLocationInstance(LocationAttr &loc) {
152*c60b897dSRiver Riddle // Handle either name or filelinecol locations.
153*c60b897dSRiver Riddle if (getToken().is(Token::string))
154*c60b897dSRiver Riddle return parseNameOrFileLineColLocation(loc);
155*c60b897dSRiver Riddle
156*c60b897dSRiver Riddle // Bare tokens required for other cases.
157*c60b897dSRiver Riddle if (!getToken().is(Token::bare_identifier))
158*c60b897dSRiver Riddle return emitWrongTokenError("expected location instance");
159*c60b897dSRiver Riddle
160*c60b897dSRiver Riddle // Check for the 'callsite' signifying a callsite location.
161*c60b897dSRiver Riddle if (getToken().getSpelling() == "callsite")
162*c60b897dSRiver Riddle return parseCallSiteLocation(loc);
163*c60b897dSRiver Riddle
164*c60b897dSRiver Riddle // If the token is 'fused', then this is a fused location.
165*c60b897dSRiver Riddle if (getToken().getSpelling() == "fused")
166*c60b897dSRiver Riddle return parseFusedLocation(loc);
167*c60b897dSRiver Riddle
168*c60b897dSRiver Riddle // Check for a 'unknown' for an unknown location.
169*c60b897dSRiver Riddle if (getToken().getSpelling() == "unknown") {
170*c60b897dSRiver Riddle consumeToken(Token::bare_identifier);
171*c60b897dSRiver Riddle loc = UnknownLoc::get(getContext());
172*c60b897dSRiver Riddle return success();
173*c60b897dSRiver Riddle }
174*c60b897dSRiver Riddle
175*c60b897dSRiver Riddle return emitWrongTokenError("expected location instance");
176*c60b897dSRiver Riddle }
177