//===- LocationParser.cpp - MLIR Location Parser -------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "Parser.h" using namespace mlir; using namespace mlir::detail; /// Specific location instances. /// /// location-inst ::= filelinecol-location | /// name-location | /// callsite-location | /// fused-location | /// unknown-location /// filelinecol-location ::= string-literal ':' integer-literal /// ':' integer-literal /// name-location ::= string-literal /// callsite-location ::= 'callsite' '(' location-inst 'at' location-inst ')' /// fused-location ::= fused ('<' attribute-value '>')? /// '[' location-inst (location-inst ',')* ']' /// unknown-location ::= 'unknown' /// ParseResult Parser::parseCallSiteLocation(LocationAttr &loc) { consumeToken(Token::bare_identifier); // Parse the '('. if (parseToken(Token::l_paren, "expected '(' in callsite location")) return failure(); // Parse the callee location. LocationAttr calleeLoc; if (parseLocationInstance(calleeLoc)) return failure(); // Parse the 'at'. if (getToken().isNot(Token::bare_identifier) || getToken().getSpelling() != "at") return emitWrongTokenError("expected 'at' in callsite location"); consumeToken(Token::bare_identifier); // Parse the caller location. LocationAttr callerLoc; if (parseLocationInstance(callerLoc)) return failure(); // Parse the ')'. if (parseToken(Token::r_paren, "expected ')' in callsite location")) return failure(); // Return the callsite location. loc = CallSiteLoc::get(calleeLoc, callerLoc); return success(); } ParseResult Parser::parseFusedLocation(LocationAttr &loc) { consumeToken(Token::bare_identifier); // Try to parse the optional metadata. Attribute metadata; if (consumeIf(Token::less)) { metadata = parseAttribute(); if (!metadata) return failure(); // Parse the '>' token. if (parseToken(Token::greater, "expected '>' after fused location metadata")) return failure(); } SmallVector locations; auto parseElt = [&] { LocationAttr newLoc; if (parseLocationInstance(newLoc)) return failure(); locations.push_back(newLoc); return success(); }; if (parseCommaSeparatedList(Delimiter::Square, parseElt, " in fused location")) return failure(); // Return the fused location. loc = FusedLoc::get(locations, metadata, getContext()); return success(); } ParseResult Parser::parseNameOrFileLineColLocation(LocationAttr &loc) { auto *ctx = getContext(); auto str = getToken().getStringValue(); consumeToken(Token::string); // If the next token is ':' this is a filelinecol location. if (consumeIf(Token::colon)) { // Parse the line number. if (getToken().isNot(Token::integer)) return emitWrongTokenError( "expected integer line number in FileLineColLoc"); auto line = getToken().getUnsignedIntegerValue(); if (!line) return emitWrongTokenError( "expected integer line number in FileLineColLoc"); consumeToken(Token::integer); // Parse the ':'. if (parseToken(Token::colon, "expected ':' in FileLineColLoc")) return failure(); // Parse the column number. if (getToken().isNot(Token::integer)) return emitWrongTokenError( "expected integer column number in FileLineColLoc"); auto column = getToken().getUnsignedIntegerValue(); if (!column.has_value()) return emitError("expected integer column number in FileLineColLoc"); consumeToken(Token::integer); loc = FileLineColLoc::get(ctx, str, line.value(), column.value()); return success(); } // Otherwise, this is a NameLoc. // Check for a child location. if (consumeIf(Token::l_paren)) { // Parse the child location. LocationAttr childLoc; if (parseLocationInstance(childLoc)) return failure(); loc = NameLoc::get(StringAttr::get(ctx, str), childLoc); // Parse the closing ')'. if (parseToken(Token::r_paren, "expected ')' after child location of NameLoc")) return failure(); } else { loc = NameLoc::get(StringAttr::get(ctx, str)); } return success(); } ParseResult Parser::parseLocationInstance(LocationAttr &loc) { // Handle either name or filelinecol locations. if (getToken().is(Token::string)) return parseNameOrFileLineColLocation(loc); // Bare tokens required for other cases. if (!getToken().is(Token::bare_identifier)) return emitWrongTokenError("expected location instance"); // Check for the 'callsite' signifying a callsite location. if (getToken().getSpelling() == "callsite") return parseCallSiteLocation(loc); // If the token is 'fused', then this is a fused location. if (getToken().getSpelling() == "fused") return parseFusedLocation(loc); // Check for a 'unknown' for an unknown location. if (getToken().getSpelling() == "unknown") { consumeToken(Token::bare_identifier); loc = UnknownLoc::get(getContext()); return success(); } return emitWrongTokenError("expected location instance"); }