llvm-project/mlir/lib/Parser/LocationParser.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

180 lines
5.7 KiB
C++
Raw Normal View History

//===- 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 emitError("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 emitError("expected valid attribute metadata");
// Parse the '>' token.
if (parseToken(Token::greater,
"expected '>' after fused location metadata"))
return failure();
}
SmallVector<Location, 4> locations;
auto parseElt = [&] {
LocationAttr newLoc;
if (parseLocationInstance(newLoc))
return failure();
locations.push_back(newLoc);
return success();
};
if (parseToken(Token::l_square, "expected '[' in fused location") ||
parseCommaSeparatedList(parseElt) ||
parseToken(Token::r_square, "expected ']' 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 emitError("expected integer line number in FileLineColLoc");
auto line = getToken().getUnsignedIntegerValue();
if (!line.hasValue())
return emitError("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 emitError("expected integer column number in FileLineColLoc");
auto column = getToken().getUnsignedIntegerValue();
if (!column.hasValue())
return emitError("expected integer column number in FileLineColLoc");
consumeToken(Token::integer);
loc = FileLineColLoc::get(ctx, str, line.getValue(), column.getValue());
return success();
}
// Otherwise, this is a NameLoc.
// Check for a child location.
if (consumeIf(Token::l_paren)) {
auto childSourceLoc = getToken().getLoc();
// Parse the child location.
LocationAttr childLoc;
if (parseLocationInstance(childLoc))
return failure();
// The child must not be another NameLoc.
if (childLoc.isa<NameLoc>())
return emitError(childSourceLoc,
"child of NameLoc cannot be another NameLoc");
loc = NameLoc::get(Identifier::get(str, ctx), childLoc);
// Parse the closing ')'.
if (parseToken(Token::r_paren,
"expected ')' after child location of NameLoc"))
return failure();
} else {
loc = NameLoc::get(Identifier::get(str, ctx));
}
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 emitError("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 emitError("expected location instance");
}