#include "Parser.h"
#include "Token.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Location.h"
#include "mlir/Support/LLVM.h"
using namespace mlir;
using namespace mlir::detail;
ParseResult Parser::parseCallSiteLocation(LocationAttr &loc) {
consumeToken(Token::bare_identifier);
if (parseToken(Token::l_paren, "expected '(' in callsite location"))
return failure();
LocationAttr calleeLoc;
if (parseLocationInstance(calleeLoc))
return failure();
if (getToken().isNot(Token::bare_identifier) ||
getToken().getSpelling() != "at")
return emitWrongTokenError("expected 'at' in callsite location");
consumeToken(Token::bare_identifier);
LocationAttr callerLoc;
if (parseLocationInstance(callerLoc))
return failure();
if (parseToken(Token::r_paren, "expected ')' in callsite location"))
return failure();
loc = CallSiteLoc::get(calleeLoc, callerLoc);
return success();
}
ParseResult Parser::parseFusedLocation(LocationAttr &loc) {
consumeToken(Token::bare_identifier);
Attribute metadata;
if (consumeIf(Token::less)) {
metadata = parseAttribute();
if (!metadata)
return failure();
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 (parseCommaSeparatedList(Delimiter::Square, parseElt,
" in fused location"))
return failure();
loc = FusedLoc::get(locations, metadata, getContext());
return success();
}
ParseResult Parser::parseNameOrFileLineColLocation(LocationAttr &loc) {
auto *ctx = getContext();
auto str = getToken().getStringValue();
consumeToken(Token::string);
if (consumeIf(Token::colon)) {
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);
if (parseToken(Token::colon, "expected ':' in FileLineColLoc"))
return failure();
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, *column);
return success();
}
if (consumeIf(Token::l_paren)) {
LocationAttr childLoc;
if (parseLocationInstance(childLoc))
return failure();
loc = NameLoc::get(StringAttr::get(ctx, str), childLoc);
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) {
if (getToken().is(Token::hash_identifier)) {
Attribute locAttr = parseExtendedAttr(Type());
if (!locAttr)
return failure();
if (!(loc = dyn_cast<LocationAttr>(locAttr)))
return emitError("expected location attribute, but got") << locAttr;
return success();
}
if (getToken().is(Token::string))
return parseNameOrFileLineColLocation(loc);
if (!getToken().is(Token::bare_identifier))
return emitWrongTokenError("expected location instance");
if (getToken().getSpelling() == "callsite")
return parseCallSiteLocation(loc);
if (getToken().getSpelling() == "fused")
return parseFusedLocation(loc);
if (getToken().getSpelling() == "unknown") {
consumeToken(Token::bare_identifier);
loc = UnknownLoc::get(getContext());
return success();
}
return emitWrongTokenError("expected location instance");
}