23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/ScopeExit.h"
25 #include "llvm/ADT/StringSet.h"
26 #include "llvm/ADT/bit.h"
27 #include "llvm/Support/Endian.h"
28 #include "llvm/Support/PrettyStackTrace.h"
29 #include "llvm/Support/SourceMgr.h"
52 StringRef contextMessage) {
57 if (
getToken().isNot(Token::l_paren))
61 if (
parseToken(Token::l_paren,
"expected '('" + contextMessage))
73 if (
parseToken(Token::less,
"expected '<'" + contextMessage))
80 if (
getToken().isNot(Token::l_square))
84 if (
parseToken(Token::l_square,
"expected '['" + contextMessage))
91 if (
getToken().isNot(Token::l_brace))
95 if (
parseToken(Token::l_brace,
"expected '{'" + contextMessage))
104 if (parseElementFn())
109 if (parseElementFn())
118 return parseToken(Token::r_paren,
"expected ')'" + contextMessage);
121 return parseToken(Token::greater,
"expected '>'" + contextMessage);
124 return parseToken(Token::r_square,
"expected ']'" + contextMessage);
127 return parseToken(Token::r_brace,
"expected '}'" + contextMessage);
129 llvm_unreachable(
"Unknown delimiter");
141 bool allowEmptyList) {
164 return emitError(SMLoc::getFromPointer(loc.getPointer() - 1), message);
186 loc = SMLoc::getFromPointer(loc.getPointer() - 1);
189 auto originalLoc = loc;
193 const char *curPtr = loc.getPointer();
197 StringRef startOfBuffer(bufferStart, curPtr - bufferStart);
202 startOfBuffer = startOfBuffer.rtrim(
" \t");
206 if (startOfBuffer.empty())
210 if (startOfBuffer.back() !=
'\n' && startOfBuffer.back() !=
'\r')
211 return emitError(SMLoc::getFromPointer(startOfBuffer.end()), message);
214 startOfBuffer = startOfBuffer.drop_back();
219 auto prevLine = startOfBuffer;
220 size_t newLineIndex = prevLine.find_last_of(
"\n\r");
221 if (newLineIndex != StringRef::npos)
222 prevLine = prevLine.drop_front(newLineIndex);
225 size_t commentStart = prevLine.find(
"//");
226 if (commentStart != StringRef::npos)
227 startOfBuffer = startOfBuffer.drop_back(prevLine.size() - commentStart);
234 const Twine &message) {
253 if (curToken.
isNot(Token::integer, Token::minus))
258 if (
parseToken(Token::integer,
"expected integer value"))
262 bool isHex = spelling.size() > 1 && spelling[1] ==
'x';
263 if (spelling.getAsInteger(isHex ? 0 : 10, result))
267 if (result.isNegative())
268 result = result.zext(result.getBitWidth() + 1);
279 std::optional<APFloat> &result,
const Token &tok,
bool isNegative,
280 const llvm::fltSemantics &semantics,
size_t typeSizeInBits) {
283 bool isHex = spelling.size() > 1 && spelling[1] ==
'x';
285 return emitError(loc,
"unexpected decimal integer literal for a "
286 "floating point value")
288 <<
"add a trailing dot to make the literal a float";
291 return emitError(loc,
"hexadecimal float literal should not have a "
297 return emitError(loc,
"hexadecimal float constant out of range for type");
299 if (&semantics == &APFloat::IEEEdouble()) {
300 result = APFloat(semantics, APInt(typeSizeInBits, *value));
304 APInt apInt(typeSizeInBits, *value);
306 return emitError(loc,
"hexadecimal float constant out of range for type");
307 result = APFloat(semantics, apInt);
328 assert(dialect &&
"expected valid dialect interface");
331 return emitError(
"expected identifier key for 'resource' entry");
337 std::pair<std::string, AsmDialectResourceHandle> &entry =
338 resources[dialect][name];
339 if (entry.first.empty()) {
343 <<
"unknown 'resource' key '" << name <<
"' for dialect '"
344 << dialect->getDialect()->getNamespace() <<
"'";
347 entry.second = *result;
359 <<
"' does not expect resource handles";
361 StringRef resourceName;
377 if (dialectName.empty() || dialectName.contains(
'.'))
388 auto shouldIgnoreOpCompletion = [&]() {
390 const char *it = loc.getPointer() - 1;
391 for (; it > bufBegin && *it !=
'\n'; --it)
392 if (!StringRef(
" \t\r").contains(*it))
396 if (shouldIgnoreOpCompletion())
414 if (name.consume_back(
"."))
455 class OperationParser :
public Parser {
457 OperationParser(
ParserState &state, ModuleOp topLevelOp);
471 struct DeferredLocInfo {
473 StringRef identifier;
477 void pushSSANameScope(
bool isIsolated);
492 bool allowResultNumber =
true);
496 Value resolveSSAUse(UnresolvedOperand useInfo,
Type type);
505 std::optional<SMLoc> getReferenceLoc(StringRef name,
unsigned number) {
506 auto &values = isolatedNameScopes.back().values;
507 if (!values.count(name) || number >= values[name].size())
509 if (values[name][number].value)
510 return values[name][number].loc;
540 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
543 std::optional<FunctionType> parsedFnType = std::nullopt);
560 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument);
569 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>;
587 bool isIsolatedNameScope =
false);
592 bool isIsolatedNameScope);
610 Block *getBlockNamed(StringRef name, SMLoc loc);
625 struct BlockDefinition {
632 struct ValueDefinition {
640 BlockDefinition &getBlockInfoByName(StringRef name) {
641 return blocksByName.back()[name];
645 void insertForwardRef(
Block *block, SMLoc loc) {
646 forwardRef.back().try_emplace(block, loc);
650 bool eraseForwardRef(
Block *block) {
return forwardRef.back().erase(block); }
653 void recordDefinition(StringRef def);
660 Value createForwardRefPlaceholder(SMLoc loc,
Type type);
663 bool isForwardRefPlaceholder(
Value value) {
664 return forwardRefPlaceholders.count(value);
671 struct IsolatedSSANameScope {
673 void recordDefinition(StringRef def) {
674 definitionsPerScope.back().insert(def);
678 void pushSSANameScope() { definitionsPerScope.push_back({}); }
681 void popSSANameScope() {
682 for (
auto &def : definitionsPerScope.pop_back_val())
683 values.erase(def.getKey());
688 llvm::StringMap<SmallVector<ValueDefinition, 1>> values;
710 std::vector<DeferredLocInfo> deferredLocsReferences;
723 OperationParser::OperationParser(
ParserState &state, ModuleOp topLevelOp)
724 :
Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) {
726 pushSSANameScope(
true);
733 OperationParser::~OperationParser() {
734 for (
auto &fwd : forwardRefPlaceholders) {
737 fwd.first.dropAllUses();
738 fwd.first.getDefiningOp()->destroy();
740 for (
const auto &scope : forwardRef) {
741 for (
const auto &fwd : scope) {
744 fwd.first->dropAllUses();
755 if (!forwardRefPlaceholders.empty()) {
758 for (
auto entry : forwardRefPlaceholders)
759 errors.push_back(entry.second.getPointer());
760 llvm::array_pod_sort(errors.begin(), errors.end());
762 for (
const char *entry : errors) {
763 auto loc = SMLoc::getFromPointer(entry);
764 emitError(loc,
"use of undeclared SSA value name");
771 auto locID = TypeID::get<DeferredLocInfo *>();
772 auto resolveLocation = [&,
this](
auto &opOrArgument) ->
LogicalResult {
773 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc());
774 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID)
776 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()];
777 Attribute attr = attributeAliases.lookup(locInfo.identifier);
780 <<
"operation location alias was never defined";
781 auto locAttr = dyn_cast<LocationAttr>(attr);
784 <<
"expected location, but found '" << attr <<
"'";
785 opOrArgument.setLoc(locAttr);
789 auto walkRes = topLevelOp->walk([&](
Operation *op) {
790 if (
failed(resolveLocation(*op)))
793 for (
Block &block : region.getBlocks())
795 if (
failed(resolveLocation(arg)))
799 if (walkRes.wasInterrupted())
803 if (
failed(popSSANameScope()))
820 void OperationParser::pushSSANameScope(
bool isIsolated) {
826 isolatedNameScopes.push_back({});
827 isolatedNameScopes.back().pushSSANameScope();
831 auto forwardRefInCurrentScope = forwardRef.pop_back_val();
834 if (!forwardRefInCurrentScope.empty()) {
837 for (
auto entry : forwardRefInCurrentScope) {
838 errors.push_back({entry.second.getPointer(), entry.first});
840 topLevelOp->getRegion(0).push_back(entry.first);
842 llvm::array_pod_sort(errors.begin(), errors.end());
844 for (
auto entry : errors) {
845 auto loc = SMLoc::getFromPointer(entry.first);
846 emitError(loc,
"reference to an undefined block");
853 auto ¤tNameScope = isolatedNameScopes.back();
854 if (currentNameScope.definitionsPerScope.size() == 1)
855 isolatedNameScopes.pop_back();
857 currentNameScope.popSSANameScope();
859 blocksByName.pop_back();
864 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo,
866 auto &entries = getSSAValueEntry(useInfo.name);
869 if (entries.size() <= useInfo.number)
870 entries.resize(useInfo.number + 1);
874 if (
auto existing = entries[useInfo.number].value) {
875 if (!isForwardRefPlaceholder(existing)) {
877 .
append(
"redefinition of SSA value '", useInfo.name,
"'")
878 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
879 .
append(
"previously defined here");
882 if (existing.getType() != value.
getType()) {
884 .
append(
"definition of SSA value '", useInfo.name,
"#",
885 useInfo.number,
"' has type ", value.
getType())
886 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
887 .
append(
"previously used here with type ", existing.getType());
893 existing.replaceAllUsesWith(value);
894 existing.getDefiningOp()->destroy();
895 forwardRefPlaceholders.erase(existing);
904 entries[useInfo.number] = {value, useInfo.location};
905 recordDefinition(useInfo.name);
914 ParseResult OperationParser::parseOptionalSSAUseList(
916 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
919 UnresolvedOperand result;
920 if (parseSSAUse(result))
922 results.push_back(result);
931 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result,
932 bool allowResultNumber) {
933 if (getToken().isCodeCompletion())
934 return codeCompleteSSAUse();
936 result.name = getTokenSpelling();
938 result.location = getToken().getLoc();
939 if (parseToken(Token::percent_identifier,
"expected SSA operand"))
943 if (getToken().is(Token::hash_identifier)) {
944 if (!allowResultNumber)
945 return emitError(
"result number not allowed in argument list");
947 if (
auto value = getToken().getHashIdentifierNumber())
948 result.number = *value;
950 return emitError(
"invalid SSA value result number");
951 consumeToken(Token::hash_identifier);
959 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo,
Type type) {
960 auto &entries = getSSAValueEntry(useInfo.name);
964 auto maybeRecordUse = [&](
Value value) {
971 if (useInfo.number < entries.size() && entries[useInfo.number].value) {
972 Value result = entries[useInfo.number].value;
975 return maybeRecordUse(result);
977 emitError(useInfo.location,
"use of value '")
979 "' expects different type than prior uses: ", type,
" vs ",
981 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
982 .
append(
"prior use here");
987 if (entries.size() <= useInfo.number)
988 entries.resize(useInfo.number + 1);
992 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value))
993 return (
emitError(useInfo.location,
"reference to invalid result number"),
998 Value result = createForwardRefPlaceholder(useInfo.location, type);
999 entries[useInfo.number] = {result, useInfo.location};
1000 return maybeRecordUse(result);
1006 ParseResult OperationParser::parseSSADefOrUseAndType(
1008 UnresolvedOperand useInfo;
1009 if (parseSSAUse(useInfo) ||
1010 parseToken(Token::colon,
"expected ':' and type for SSA operand"))
1017 return action(useInfo, type);
1026 ParseResult OperationParser::parseOptionalSSAUseAndTypeList(
1029 if (parseOptionalSSAUseList(valueIDs))
1033 if (valueIDs.empty())
1037 if (parseToken(Token::colon,
"expected ':' in operand list") ||
1038 parseTypeListNoParens(types))
1041 if (valueIDs.size() != types.size())
1043 << valueIDs.size() <<
" types to match operand list";
1045 results.reserve(valueIDs.size());
1046 for (
unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1047 if (
auto value = resolveSSAUse(valueIDs[i], types[i]))
1048 results.push_back(value);
1057 void OperationParser::recordDefinition(StringRef def) {
1058 isolatedNameScopes.back().recordDefinition(def);
1062 auto OperationParser::getSSAValueEntry(StringRef name)
1064 return isolatedNameScopes.back().values[name];
1068 Value OperationParser::createForwardRefPlaceholder(SMLoc loc,
Type type) {
1075 auto name =
OperationName(
"builtin.unrealized_conversion_cast", getContext());
1077 getEncodedSourceLocation(loc), name, type, {},
1078 std::nullopt, {}, 0);
1079 forwardRefPlaceholders[op->
getResult(0)] = loc;
1100 auto loc = getToken().getLoc();
1102 size_t numExpectedResults = 0;
1103 if (getToken().is(Token::percent_identifier)) {
1107 Token nameTok = getToken();
1108 if (parseToken(Token::percent_identifier,
1109 "expected valid ssa identifier"))
1113 size_t expectedSubResults = 1;
1114 if (consumeIf(Token::colon)) {
1116 if (!getToken().is(Token::integer))
1117 return emitWrongTokenError(
"expected integer number of results");
1120 auto val = getToken().getUInt64IntegerValue();
1121 if (!val || *val < 1)
1123 "expected named operation to have at least 1 result");
1124 consumeToken(Token::integer);
1125 expectedSubResults = *val;
1128 resultIDs.emplace_back(nameTok.
getSpelling(), expectedSubResults,
1130 numExpectedResults += expectedSubResults;
1136 if (parseToken(Token::equal,
"expected '=' after SSA name"))
1141 Token nameTok = getToken();
1142 if (nameTok.
is(Token::bare_identifier) || nameTok.
isKeyword())
1143 op = parseCustomOperation(resultIDs);
1144 else if (nameTok.
is(Token::string))
1145 op = parseGenericOperation();
1147 return codeCompleteStringDialectOrOperationName(nameTok.
getStringValue());
1149 return codeCompleteDialectOrElidedOpName(loc);
1151 return emitWrongTokenError(
"expected operation name in quotes");
1158 if (!resultIDs.empty()) {
1160 return emitError(loc,
"cannot name an operation with no results");
1162 return emitError(loc,
"operation defines ")
1164 << numExpectedResults <<
" to bind";
1168 unsigned resultIt = 0;
1170 asmResultGroups.reserve(resultIDs.size());
1171 for (ResultRecord &record : resultIDs) {
1172 asmResultGroups.emplace_back(resultIt, std::get<2>(record));
1173 resultIt += std::get<1>(record);
1181 unsigned opResI = 0;
1182 for (ResultRecord &resIt : resultIDs) {
1183 for (
unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) {
1184 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes},
1193 getToken().getLoc());
1204 if (getToken().isCodeCompletion())
1205 return codeCompleteBlock();
1208 if (!getToken().is(Token::caret_identifier))
1209 return emitWrongTokenError(
"expected block name");
1210 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1221 if (parseToken(Token::l_square,
"expected '['"))
1224 auto parseElt = [
this, &destinations] {
1227 destinations.push_back(dest);
1230 return parseCommaSeparatedListUntil(Token::r_square, parseElt,
1239 struct CleanupOpStateRegions {
1240 ~CleanupOpStateRegions() {
1242 regionsToClean.reserve(state.regions.size());
1243 for (
auto ®ion : state.regions)
1245 for (
auto &block : *region)
1252 ParseResult OperationParser::parseGenericOperationAfterOpName(
1256 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1258 std::optional<FunctionType> parsedFnType) {
1262 if (!parsedOperandUseInfo) {
1263 if (parseToken(Token::l_paren,
"expected '(' to start operand list") ||
1264 parseOptionalSSAUseList(opInfo) ||
1265 parseToken(Token::r_paren,
"expected ')' to end operand list")) {
1268 parsedOperandUseInfo = opInfo;
1272 if (!parsedSuccessors) {
1273 if (getToken().is(Token::l_square)) {
1276 return emitError(
"successors in non-terminator");
1279 if (parseSuccessors(successors))
1288 if (!parsedRegions) {
1289 if (consumeIf(Token::l_paren)) {
1293 if (parseRegion(*result.
regions.back(), {}))
1295 }
while (consumeIf(Token::comma));
1296 if (parseToken(Token::r_paren,
"expected ')' to end region list"))
1304 if (!parsedAttributes) {
1305 if (getToken().is(Token::l_brace)) {
1315 if (!parsedFnType) {
1316 if (parseToken(Token::colon,
"expected ':' followed by operation type"))
1319 typeLoc = getEncodedSourceLocation(getToken().getLoc());
1323 auto fnType = type.
dyn_cast<FunctionType>();
1327 parsedFnType = fnType;
1330 result.
addTypes(parsedFnType->getResults());
1334 if (operandTypes.size() != parsedOperandUseInfo->size()) {
1335 auto plural =
"s"[parsedOperandUseInfo->size() == 1];
1337 << parsedOperandUseInfo->size() <<
" operand type" << plural
1338 <<
" but had " << operandTypes.size();
1342 for (
unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) {
1344 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i]));
1352 Operation *OperationParser::parseGenericOperation() {
1354 auto srcLocation = getEncodedSourceLocation(getToken().getLoc());
1356 std::string name = getToken().getStringValue();
1358 return (
emitError(
"empty operation name is invalid"),
nullptr);
1359 if (name.find(
'\0') != StringRef::npos)
1360 return (
emitError(
"null character not allowed in operation name"),
nullptr);
1362 consumeToken(Token::string);
1365 CleanupOpStateRegions guard{result};
1369 StringRef dialectName = StringRef(name).split(
'.').first;
1370 if (!getContext()->getLoadedDialect(dialectName) &&
1371 !getContext()->getOrLoadDialect(dialectName)) {
1372 if (!getContext()->allowsUnregisteredDialects()) {
1375 emitError(
"operation being parsed with an unregistered dialect. If "
1376 "this is intended, please use -allow-unregistered-dialect "
1377 "with the MLIR tool used");
1390 if (parseGenericOperationAfterOpName(result))
1395 if (parseTrailingLocationSpecifier(op))
1400 Operation *OperationParser::parseGenericOperation(
Block *insertBlock,
1402 Token nameToken = getToken();
1405 opBuilder.setInsertionPoint(insertBlock, insertPt);
1406 Operation *op = parseGenericOperation();
1414 getToken().getLoc());
1419 class CustomOpAsmParser :
public AsmParserImpl<OpAsmParser> {
1424 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser)
1426 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove),
1427 opName(opName), parser(parser) {
1428 (void)isIsolatedFromAbove;
1434 if (parseAssembly(*
this, opState))
1440 std::optional<NamedAttribute> duplicate =
1443 return emitError(getNameLoc(),
"attribute '")
1444 << duplicate->getName().getValue()
1445 <<
"' occurs more than once in the attribute list";
1451 return parser.parseGenericOperation(insertBlock, insertPt);
1455 return parser.parseCustomOperationName();
1462 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1464 std::optional<FunctionType> parsedFnType)
final {
1465 return parser.parseGenericOperationAfterOpName(
1466 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
1467 parsedAttributes, parsedFnType);
1482 std::pair<StringRef, unsigned>
1483 getResultName(
unsigned resultNo)
const override {
1485 for (
const auto &entry : resultIDs) {
1486 if (resultNo < std::get<1>(entry)) {
1488 StringRef name = std::get<0>(entry).drop_front();
1489 return {name, resultNo};
1491 resultNo -= std::get<1>(entry);
1500 size_t getNumResults()
const override {
1502 for (
auto &entry : resultIDs)
1503 count += std::get<1>(entry);
1518 ParseResult parseOperand(UnresolvedOperand &result,
1519 bool allowResultNumber =
true)
override {
1521 if (parser.parseSSAUse(useInfo, allowResultNumber))
1531 bool allowResultNumber =
true)
override {
1532 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1533 return parseOperand(result, allowResultNumber);
1534 return std::nullopt;
1541 bool allowResultNumber =
true,
1542 int requiredOperandCount = -1)
override {
1547 Token tok = parser.getToken();
1551 if (requiredOperandCount == -1 || requiredOperandCount == 0)
1555 if (tok.
isAny(Token::l_paren, Token::l_square))
1556 return parser.emitError(
"unexpected delimiter");
1557 return parser.emitWrongTokenError(
"expected operand");
1562 return parseOperand(result.emplace_back(), allowResultNumber);
1565 auto startLoc = parser.getToken().getLoc();
1570 if (requiredOperandCount != -1 &&
1571 result.size() !=
static_cast<size_t>(requiredOperandCount))
1573 << requiredOperandCount <<
" operands";
1578 ParseResult resolveOperand(
const UnresolvedOperand &operand,
Type type,
1580 if (
auto value = parser.resolveSSAUse(operand, type)) {
1581 result.push_back(value);
1595 auto parseElement = [&](
bool isSymbol) ->
ParseResult {
1596 UnresolvedOperand operand;
1597 if (parseOperand(operand))
1600 symOperands.push_back(operand);
1602 dimOperands.push_back(operand);
1607 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter))
1611 mapAttr = AffineMapAttr::get(map);
1612 attrs.
push_back(parser.builder.getNamedAttr(attrName, mapAttr));
1616 operands.assign(dimOperands.begin(), dimOperands.end());
1617 operands.append(symOperands.begin(), symOperands.end());
1626 auto parseElement = [&](
bool isSymbol) ->
ParseResult {
1627 UnresolvedOperand operand;
1628 if (parseOperand(operand))
1631 symbOperands.push_back(operand);
1633 dimOperands.push_back(operand);
1637 return parser.parseAffineExprOfSSAIds(expr, parseElement);
1650 ParseResult parseArgument(Argument &result,
bool allowType =
false,
1651 bool allowAttrs =
false)
override {
1653 if (parseOperand(result.ssaName,
false) ||
1654 (allowType && parseColonType(result.type)) ||
1655 (allowAttrs && parseOptionalAttrDict(attrs)) ||
1656 parseOptionalLocationSpecifier(result.sourceLoc))
1664 bool allowAttrs)
override {
1665 if (parser.getToken().is(Token::percent_identifier))
1666 return parseArgument(result, allowType, allowAttrs);
1667 return std::nullopt;
1671 Delimiter delimiter,
bool allowType,
1672 bool allowAttrs)
override {
1675 parser.getToken().isNot(Token::percent_identifier))
1679 return parseArgument(result.emplace_back(), allowType, allowAttrs);
1682 " in argument list");
1692 bool enableNameShadowing)
override {
1694 (void)isIsolatedFromAbove;
1695 assert((!enableNameShadowing || isIsolatedFromAbove) &&
1696 "name shadowing is only allowed on isolated regions");
1697 if (parser.parseRegion(region, arguments, enableNameShadowing))
1705 bool enableNameShadowing)
override {
1706 if (parser.getToken().isNot(Token::l_brace))
1707 return std::nullopt;
1708 return parseRegion(region, arguments, enableNameShadowing);
1715 parseOptionalRegion(std::unique_ptr<Region> ®ion,
1717 bool enableNameShadowing =
false)
override {
1718 if (parser.getToken().isNot(Token::l_brace))
1719 return std::nullopt;
1720 std::unique_ptr<Region> newRegion = std::make_unique<Region>();
1721 if (parseRegion(*newRegion, arguments, enableNameShadowing))
1724 region = std::move(newRegion);
1734 return parser.parseSuccessor(dest);
1739 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier))
1740 return std::nullopt;
1741 return parseSuccessor(dest);
1746 parseSuccessorAndUseList(
Block *&dest,
1748 if (parseSuccessor(dest))
1753 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) {
1768 if (
failed(parseOptionalLParen()))
1769 return std::nullopt;
1772 if (parseArgument(lhs.emplace_back()) || parseEqual() ||
1773 parseOperand(rhs.emplace_back()))
1777 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt);
1782 parseOptionalLocationSpecifier(std::optional<Location> &result)
override {
1784 if (!parser.consumeIf(Token::kw_loc))
1787 if (parser.parseToken(Token::l_paren,
"expected '(' in location"))
1790 Token tok = parser.getToken();
1794 if (tok.
is(Token::hash_identifier)) {
1795 if (parser.parseLocationAlias(directLoc))
1797 }
else if (parser.parseLocationInstance(directLoc)) {
1801 if (parser.parseToken(Token::r_paren,
"expected ')' in location"))
1814 bool isIsolatedFromAbove;
1818 OperationParser &parser;
1823 Token nameTok = getToken();
1830 std::optional<RegisteredOperationName> opInfo =
1837 auto opNameSplit = opName.split(
'.');
1838 StringRef dialectName = opNameSplit.first;
1839 std::string opNameStorage;
1840 if (opNameSplit.second.empty()) {
1842 if (getToken().isCodeCompletion() && opName.back() ==
'.')
1843 return codeCompleteOperationName(dialectName);
1845 dialectName = getState().defaultDialectStack.back();
1846 opNameStorage = (dialectName +
"." + opName).str();
1847 opName = opNameStorage;
1852 getContext()->getOrLoadDialect(dialectName);
1858 SMLoc opLoc = getToken().
getLoc();
1859 StringRef originalOpName = getTokenSpelling();
1864 StringRef opName = opNameInfo->getStringRef();
1870 bool isIsolatedFromAbove =
false;
1872 StringRef defaultDialect =
"";
1873 if (
auto opInfo = opNameInfo->getRegisteredInfo()) {
1874 parseAssemblyFn = opInfo->getParseAssemblyFn();
1876 auto *iface = opInfo->getInterface<OpAsmOpInterface>();
1877 if (iface && !iface->getDefaultDialect().empty())
1878 defaultDialect = iface->getDefaultDialect();
1880 std::optional<Dialect::ParseOpHook> dialectHook;
1881 Dialect *dialect = opNameInfo->getDialect();
1884 emitError(opLoc) <<
"Dialect `" << opNameInfo->getDialectNamespace()
1885 <<
"' not found for custom op '" << originalOpName
1887 if (originalOpName != opName)
1888 diag <<
" (tried '" << opName <<
"' as well)";
1889 auto ¬e =
diag.attachNote();
1890 note <<
"Registered dialects: ";
1891 llvm::interleaveComma(getContext()->getAvailableDialects(), note,
1892 [&](StringRef dialect) { note << dialect; });
1893 note <<
" ; for more info on dialect registration see "
1894 "https://mlir.llvm.org/getting_started/Faq/"
1895 "#registered-loaded-dependent-whats-up-with-dialects-management";
1901 emitError(opLoc) <<
"custom op '" << originalOpName <<
"' is unknown";
1902 if (originalOpName != opName)
1903 diag <<
" (tried '" << opName <<
"' as well)";
1906 parseAssemblyFn = *dialectHook;
1908 getState().defaultDialectStack.push_back(defaultDialect);
1909 auto restoreDefaultDialect = llvm::make_scope_exit(
1910 [&]() { getState().defaultDialectStack.pop_back(); });
1914 llvm::PrettyStackTraceFormat fmt(
"MLIR Parser: custom op parser '%s'",
1915 opNameInfo->getIdentifier().data());
1918 auto srcLocation = getEncodedSourceLocation(opLoc);
1926 CleanupOpStateRegions guard{opState};
1927 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn,
1928 isIsolatedFromAbove, opName, *
this);
1929 if (opAsmParser.parseOperation(opState))
1933 if (opAsmParser.didEmitError())
1938 if (parseTrailingLocationSpecifier(op))
1944 Token tok = getToken();
1945 consumeToken(Token::hash_identifier);
1946 StringRef identifier = tok.
getSpelling().drop_front();
1947 if (identifier.contains(
'.')) {
1949 <<
"expected location, but found dialect attribute: '#" << identifier
1956 if (!(loc = dyn_cast<LocationAttr>(attr)))
1958 <<
"expected location, but found '" << attr <<
"'";
1962 loc = OpaqueLoc::get(deferredLocsReferences.size(),
1963 TypeID::get<DeferredLocInfo *>(),
1964 UnknownLoc::get(getContext()));
1965 deferredLocsReferences.push_back(DeferredLocInfo{tok.
getLoc(), identifier});
1971 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) {
1973 if (!consumeIf(Token::kw_loc))
1975 if (parseToken(Token::l_paren,
"expected '(' in location"))
1977 Token tok = getToken();
1982 if (tok.
is(Token::hash_identifier)) {
1983 if (parseLocationAlias(directLoc))
1985 }
else if (parseLocationInstance(directLoc)) {
1989 if (parseToken(Token::r_paren,
"expected ')' in location"))
1992 if (
auto *op = opOrArgument.dyn_cast<
Operation *>())
2005 bool isIsolatedNameScope) {
2007 Token lBraceTok = getToken();
2008 if (parseToken(Token::l_brace,
"expected '{' to begin a region"))
2016 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) &&
2017 parseRegionBody(region, lBraceTok.
getLoc(), entryArguments,
2018 isIsolatedNameScope)) {
2021 consumeToken(Token::r_brace);
2032 bool isIsolatedNameScope) {
2033 auto currentPt = opBuilder.saveInsertionPoint();
2036 pushSSANameScope(isIsolatedNameScope);
2039 auto owningBlock = std::make_unique<Block>();
2040 Block *block = owningBlock.get();
2045 if (state.
asmState && getToken().isNot(Token::caret_identifier))
2049 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) {
2051 if (getToken().is(Token::caret_identifier))
2052 return emitError(
"invalid block name in region with named arguments");
2054 for (
auto &entryArg : entryArguments) {
2055 auto &argInfo = entryArg.ssaName;
2058 if (
auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) {
2059 return emitError(argInfo.location,
"region entry argument '" +
2061 "' is already in use")
2062 .
attachNote(getEncodedSourceLocation(*defLoc))
2063 <<
"previously referenced here";
2065 Location loc = entryArg.sourceLoc.has_value()
2066 ? *entryArg.sourceLoc
2067 : getEncodedSourceLocation(argInfo.location);
2075 if (addDefinition(argInfo, arg))
2080 if (parseBlock(block))
2084 if (!entryArguments.empty() &&
2086 return emitError(
"entry block arguments were already defined");
2090 region.
push_back(owningBlock.release());
2091 while (getToken().isNot(Token::r_brace)) {
2092 Block *newBlock =
nullptr;
2093 if (parseBlock(newBlock))
2099 if (popSSANameScope())
2103 opBuilder.restoreInsertionPoint(currentPt);
2121 if (block && getToken().isNot(Token::caret_identifier))
2122 return parseBlockBody(block);
2124 SMLoc nameLoc = getToken().getLoc();
2125 auto name = getTokenSpelling();
2126 if (parseToken(Token::caret_identifier,
"expected block name"))
2130 auto &blockAndLoc = getBlockInfoByName(name);
2131 blockAndLoc.loc = nameLoc;
2136 std::unique_ptr<Block> inflightBlock;
2137 auto cleanupOnFailure = llvm::make_scope_exit([&] {
2139 inflightBlock->dropAllDefinedValueUses();
2144 if (!blockAndLoc.block) {
2146 blockAndLoc.block = block;
2148 inflightBlock = std::make_unique<Block>();
2149 blockAndLoc.block = inflightBlock.get();
2156 }
else if (!eraseForwardRef(blockAndLoc.block)) {
2157 return emitError(nameLoc,
"redefinition of block '") << name <<
"'";
2161 inflightBlock.reset(blockAndLoc.block);
2167 block = blockAndLoc.block;
2170 if (getToken().is(Token::l_paren))
2171 if (parseOptionalBlockArgList(block))
2173 if (parseToken(Token::colon,
"expected ':' after block name"))
2182 (void)inflightBlock.release();
2188 opBuilder.setInsertionPointToEnd(block);
2191 while (getToken().isNot(Token::caret_identifier, Token::r_brace))
2192 if (parseOperation())
2201 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) {
2202 BlockDefinition &blockDef = getBlockInfoByName(name);
2203 if (!blockDef.block) {
2204 blockDef = {
new Block(), loc};
2205 insertForwardRef(blockDef.block, blockDef.loc);
2212 return blockDef.block;
2222 if (getToken().is(Token::r_brace))
2228 unsigned nextArgument = 0;
2231 return parseSSADefOrUseAndType(
2237 if (definingExistingArgs) {
2240 return emitError(
"too many arguments specified in argument list");
2245 return emitError(
"argument and block argument type mismatch");
2247 auto loc = getEncodedSourceLocation(useInfo.location);
2253 if (parseTrailingLocationSpecifier(arg))
2261 return addDefinition(useInfo, arg);
2270 ParseResult OperationParser::codeCompleteSSAUse() {
2271 std::string detailData;
2272 llvm::raw_string_ostream detailOS(detailData);
2273 for (IsolatedSSANameScope &scope : isolatedNameScopes) {
2274 for (
auto &it : scope.values) {
2275 if (it.second.empty())
2277 Value frontValue = it.second.front().value;
2281 if (
auto result = dyn_cast<OpResult>(frontValue)) {
2282 if (!forwardRefPlaceholders.count(result))
2283 detailOS << result.getOwner()->getName() <<
": ";
2290 detailOS << frontValue.
getType();
2295 if (it.second.size() > 1)
2296 detailOS <<
", ...";
2299 it.getKey(), std::move(detailOS.str()));
2306 ParseResult OperationParser::codeCompleteBlock() {
2309 StringRef spelling = getTokenSpelling();
2310 if (!(spelling.empty() || spelling ==
"^"))
2313 for (
const auto &it : blocksByName.back())
2325 class TopLevelOperationParser :
public Parser {
2362 ParsedResourceEntry(StringRef key, SMLoc keyLoc,
Token value,
Parser &p)
2363 : key(key), keyLoc(keyLoc), value(value), p(p) {}
2364 ~ParsedResourceEntry()
override =
default;
2366 StringRef getKey() const final {
return key; }
2371 if (value.isAny(Token::kw_true, Token::kw_false))
2373 return value.getSpelling().startswith(
"\"0x")
2379 if (value.is(Token::kw_true))
2381 if (value.is(Token::kw_false))
2383 return p.emitError(value.getLoc(),
2384 "expected 'true' or 'false' value for key '" + key +
2389 if (value.isNot(Token::string))
2390 return p.emitError(value.getLoc(),
2391 "expected string value for key '" + key +
"'");
2392 return value.getStringValue();
2396 parseAsBlob(BlobAllocatorFn allocator)
const final {
2400 std::optional<std::string> blobData =
2401 value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
2403 return p.emitError(value.getLoc(),
2404 "expected hex string blob for key '" + key +
"'");
2408 if (blobData->size() <
sizeof(uint32_t)) {
2409 return p.emitError(value.getLoc(),
2410 "expected hex string blob for key '" + key +
2411 "' to encode alignment in first 4 bytes");
2413 llvm::support::ulittle32_t align;
2414 memcpy(&align, blobData->data(),
sizeof(uint32_t));
2417 StringRef data = StringRef(*blobData).drop_front(
sizeof(uint32_t));
2424 assert(llvm::isAddrAligned(llvm::Align(align), blob.
getData().data()) &&
2426 "blob allocator did not return a properly aligned address");
2439 ParseResult TopLevelOperationParser::parseAttributeAliasDef() {
2440 assert(getToken().is(Token::hash_identifier));
2441 StringRef aliasName = getTokenSpelling().drop_front();
2445 return emitError(
"redefinition of attribute alias id '" + aliasName +
"'");
2448 if (aliasName.contains(
'.'))
2449 return emitError(
"attribute names with a '.' are reserved for "
2450 "dialect-defined names");
2452 consumeToken(Token::hash_identifier);
2455 if (parseToken(Token::equal,
"expected '=' in attribute alias definition"))
2467 ParseResult TopLevelOperationParser::parseTypeAliasDef() {
2468 assert(getToken().is(Token::exclamation_identifier));
2469 StringRef aliasName = getTokenSpelling().drop_front();
2473 return emitError(
"redefinition of type alias id '" + aliasName +
"'");
2476 if (aliasName.contains(
'.'))
2477 return emitError(
"type names with a '.' are reserved for "
2478 "dialect-defined names");
2479 consumeToken(Token::exclamation_identifier);
2482 if (parseToken(Token::equal,
"expected '=' in type alias definition"))
2495 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() {
2496 consumeToken(Token::file_metadata_begin);
2497 return parseCommaSeparatedListUntil(
2500 SMLoc keyLoc = getToken().getLoc();
2502 if (
failed(parseOptionalKeyword(&key)))
2503 return emitError(
"expected identifier key in file "
2504 "metadata dictionary");
2505 if (parseToken(Token::colon,
"expected ':'"))
2509 if (key ==
"dialect_resources")
2510 return parseDialectResourceFileMetadata();
2511 if (key ==
"external_resources")
2512 return parseExternalResourceFileMetadata();
2513 return emitError(keyLoc,
"unknown key '" + key +
2514 "' in file metadata dictionary");
2518 ParseResult TopLevelOperationParser::parseResourceFileMetadata(
2520 if (parseToken(Token::l_brace,
"expected '{'"))
2523 return parseCommaSeparatedListUntil(Token::r_brace, [&]() ->
ParseResult {
2525 SMLoc nameLoc = getToken().getLoc();
2527 if (
failed(parseOptionalKeyword(&name)))
2528 return emitError(
"expected identifier key for 'resource' entry");
2530 if (parseToken(Token::colon,
"expected ':'") ||
2531 parseToken(Token::l_brace,
"expected '{'"))
2533 return parseBody(name, nameLoc);
2537 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() {
2538 return parseResourceFileMetadata([&](StringRef name,
2541 Dialect *dialect = getContext()->getOrLoadDialect(name);
2543 return emitError(nameLoc,
"dialect '" + name +
"' is unknown");
2544 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect);
2546 return emitError() <<
"unexpected 'resource' section for dialect '"
2550 return parseCommaSeparatedListUntil(Token::r_brace, [&]() ->
ParseResult {
2552 SMLoc keyLoc = getToken().getLoc();
2554 if (
failed(parseResourceHandle(handler, key)) ||
2555 parseToken(Token::colon,
"expected ':'"))
2557 Token valueTok = getToken();
2560 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2561 return handler->parseResource(entry);
2566 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() {
2567 return parseResourceFileMetadata([&](StringRef name,
2574 <<
"ignoring unknown external resources for '" << name <<
"'";
2577 return parseCommaSeparatedListUntil(Token::r_brace, [&]() ->
ParseResult {
2579 SMLoc keyLoc = getToken().getLoc();
2581 if (
failed(parseOptionalKeyword(&key)))
2583 "expected identifier key for 'external_resources' entry");
2584 if (parseToken(Token::colon,
"expected ':'"))
2586 Token valueTok = getToken();
2591 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2601 OperationParser opParser(state, topLevelOp.get());
2603 switch (getToken().getKind()) {
2606 if (opParser.parseOperation())
2612 if (opParser.finalize())
2617 auto &parsedOps = topLevelOp->getBody()->getOperations();
2619 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(),
2631 case Token::hash_identifier:
2632 if (parseAttributeAliasDef())
2637 case Token::exclamation_identifier:
2638 if (parseTypeAliasDef())
2643 case Token::file_metadata_begin:
2644 if (parseFileMetadataDictionary())
2657 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2660 FileLineColLoc::get(config.
getContext(), sourceBuf->getBufferIdentifier(),
2664 ParserState state(sourceMgr, config, aliasState, asmState,
2665 codeCompleteContext);
2666 return TopLevelOperationParser(state).parse(block, parserLoc);
static std::string diag(const llvm::Value &value)
static ParseResult parseOptionalOperand(OpAsmParser &parser, StringRef keyword, OpAsmParser::UnresolvedOperand &operand, Type type, bool &hasOptional, OperationState &result)
static ParseResult parseOperandList(OpAsmParser &parser, StringRef keyword, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &args, SmallVectorImpl< Type > &argTypes, OperationState &result)
#define MLIR_DECLARE_EXPLICIT_TYPE_ID(CLASS_NAME)
#define MLIR_DEFINE_EXPLICIT_TYPE_ID(CLASS_NAME)
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
This class represents a single parsed resource entry.
This class provides an abstract interface into the parser for hooking in code completion events.
virtual void completeExpectedTokens(ArrayRef< StringRef > tokens, bool optional)=0
Signal a completion for the given expected tokens, which are optional if optional is set.
virtual void completeAttribute(const llvm::StringMap< Attribute > &aliases)=0
Signal a completion for an attribute.
virtual void appendBlockCompletion(StringRef name)=0
Append the given block as a code completion result for block name completions.
virtual void appendSSAValueCompletion(StringRef name, std::string typeData)=0
Append the given SSA value as a code completion result for SSA value completions.
virtual void completeDialectAttributeOrAlias(const llvm::StringMap< Attribute > &aliases)=0
virtual void completeType(const llvm::StringMap< Type > &aliases)=0
Signal a completion for a type.
virtual void completeOperationName(StringRef dialectName)=0
Signal code completion for an operation name within the given dialect.
virtual void completeDialectName(StringRef prefix)=0
Signal code completion for a dialect name, with an optional prefix.
virtual void completeDialectTypeOrAlias(const llvm::StringMap< Type > &aliases)=0
virtual ~AsmParserCodeCompleteContext()
This class represents state from a parsed MLIR textual format string.
void startRegionDefinition()
Start a definition for a region nested under the current operation.
void startOperationDefinition(const OperationName &opName)
Start a definition for an operation with the given name.
void finalizeOperationDefinition(Operation *op, SMRange nameLoc, SMLoc endLoc, ArrayRef< std::pair< unsigned, SMLoc >> resultGroups=std::nullopt)
Finalize the most recently started operation definition.
void initialize(Operation *topLevelOp)
Initialize the state in preparation for populating more parser state under the given top-level operat...
void finalize(Operation *topLevelOp)
Finalize any in-progress parser state under the given top-level operation.
void addUses(Value value, ArrayRef< SMLoc > locations)
Add a source uses of the given value.
void refineDefinition(Value oldValue, Value newValue)
Refine the oldValue to the newValue.
void finalizeRegionDefinition()
Finalize the most recently started region definition.
void addDefinition(Block *block, SMLoc location)
Add a definition of the given entity.
Delimiter
These are the supported delimiters around operand lists and region argument lists,...
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ OptionalLessGreater
<> brackets supporting zero or more ops, or nothing.
@ Braces
{} brackets surrounding zero or more operands.
@ OptionalBraces
{} brackets surrounding zero or more operands, or nothing.
@ OptionalParen
Parens supporting zero or more operands, or nothing.
@ Square
Square brackets surrounding zero or more operands.
@ LessGreater
<> brackets surrounding zero or more operands.
@ OptionalSquare
Square brackets supporting zero or more ops, or nothing.
The following classes enable support for parsing and printing resources within MLIR assembly formats.
MutableArrayRef< char > getMutableData()
Return a mutable reference to the raw underlying data of this blob.
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
bool isMutable() const
Return if the data of this blob is mutable.
This class represents an instance of a resource parser.
virtual LogicalResult parseResource(AsmParsedResourceEntry &entry)=0
Parse the given resource entry.
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
OpListType::iterator iterator
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
void dropAllDefinedValueUses()
This drops all uses of values defined in this block or in the blocks of nested regions wherever the u...
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
OpListType & getOperations()
BlockArgListType getArguments()
Diagnostic & append(Arg1 &&arg1, Arg2 &&arg2, Args &&...args)
Append arguments to the diagnostic.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
virtual std::optional< ParseOpHook > getParseOperationHook(StringRef opName) const
Return the hook to parse an operation registered to this dialect, if any.
StringRef getNamespace() const
This class provides support for representing a failure result, or a valid value of type T.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
InFlightDiagnostic & append(Args &&...args) &
Append arguments to the diagnostic.
const char * getBufferBegin()
Returns the start of the buffer.
Location objects represent source locations information in MLIR.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
std::optional< NamedAttribute > findDuplicate() const
Returns an entry with a duplicate name the list, if it exists, else returns std::nullopt.
virtual std::string getResourceKey(const AsmDialectResourceHandle &handle) const
Return a key to use for the given resource.
virtual FailureOr< AsmDialectResourceHandle > declareResource(StringRef key) const
Declare a resource with the given key, returning a handle to use for any references of this resource ...
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
This class provides the API for ops that are known to be isolated from above.
This class provides the API for ops that are known to be terminators.
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &)> ParseAssemblyFn
bool mightHaveTrait() const
Returns true if the operation might have the provided trait.
bool isRegistered() const
Return if this operation is registered.
Operation is the basic unit of execution within MLIR.
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
unsigned getNumResults()
Return the number of results held by this operation.
This class implements Optional functionality for ParseResult.
This class represents success/failure for parsing-like operations that find it important to chain tog...
This class represents a configuration for the MLIR assembly parser.
bool shouldVerifyAfterParse() const
Returns if the parser should verify the IR after parsing.
MLIRContext * getContext() const
Return the MLIRContext to be used when parsing.
AsmResourceParser * getResourceParser(StringRef name) const
Return the resource parser registered to the given name, or nullptr if no parser with name is registe...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
void push_back(Block *block)
static std::optional< RegisteredOperationName > lookup(StringRef name, MLIRContext *ctx)
Lookup the registered operation information for the given operation.
This represents a token in the MLIR syntax.
bool isCodeCompletionFor(Kind kind) const
Returns true if the current token represents a code completion for the "normal" token type.
SMRange getLocRange() const
bool isKeyword() const
Return true if this is one of the keyword token kinds (e.g. kw_if).
static StringRef getTokenSpelling(Kind kind)
Given a punctuation or keyword token kind, return the spelling of the token as a string.
std::string getStringValue() const
Given a token containing a string literal, return its value, including removing the quote characters ...
static std::optional< uint64_t > getUInt64IntegerValue(StringRef spelling)
For an integer token, return its value as an uint64_t.
bool isAny(Kind k1, Kind k2) const
bool isCodeCompletion() const
Returns true if the current token represents a code completion.
StringRef getSpelling() const
bool isOrIsCodeCompletionFor(Kind kind) const
Returns true if the current token is the given type, or represents a code completion for that type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
static WalkResult advance()
static WalkResult interrupt()
This class provides the implementation of the generic parser methods within AsmParser.
InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override
Emit a diagnostic at the specified location and return failure.
This class implement support for parsing global entities like attributes and types.
ParseResult parseOptionalKeyword(StringRef *keyword)
Parse a keyword, if present, into 'keyword'.
ParseResult parseToken(Token::Kind expectedToken, const Twine &message)
Consume the specified token if present and return success.
ParseResult parseCommaSeparatedListUntil(Token::Kind rightToken, function_ref< ParseResult()> parseElement, bool allowEmptyList=true)
Parse a comma-separated list of elements up until the specified end token.
ParseResult codeCompleteOperationName(StringRef dialectName)
ParserState & getState() const
Location getEncodedSourceLocation(SMLoc loc)
Encode the specified source location information into an attribute for attachment to the IR.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error and return failure.
ParserState & state
The Parser is subclassed and reinstantiated.
ParseResult codeCompleteDialectName()
The set of various code completion methods.
StringRef getTokenSpelling() const
void consumeToken()
Advance the current lexer onto the next token.
ParseResult codeCompleteExpectedTokens(ArrayRef< StringRef > tokens)
Attribute codeCompleteAttribute()
ParseResult codeCompleteDialectOrElidedOpName(SMLoc loc)
InFlightDiagnostic emitWrongTokenError(const Twine &message={})
Emit an error about a "wrong token".
ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())
Parse a list of comma-separated items with an optional delimiter.
OptionalParseResult parseOptionalInteger(APInt &result)
Parse an optional integer value from the stream.
bool isCurrentTokenAKeyword() const
Returns true if the current token corresponds to a keyword.
ParseResult codeCompleteStringDialectOrOperationName(StringRef name)
ParseResult parseFloatFromIntegerLiteral(std::optional< APFloat > &result, const Token &tok, bool isNegative, const llvm::fltSemantics &semantics, size_t typeSizeInBits)
Parse a floating point value from an integer literal token.
ParseResult codeCompleteOptionalTokens(ArrayRef< StringRef > tokens)
const Token & getToken() const
Return the current token the parser is inspecting.
FailureOr< AsmDialectResourceHandle > parseResourceHandle(const OpAsmDialectInterface *dialect, StringRef &name)
Parse a handle to a dialect resource within the assembly format.
bool consumeIf(Token::Kind kind)
If the current token has the specified kind, consume it and return true.
Attribute codeCompleteDialectSymbol(const llvm::StringMap< Attribute > &aliases)
LogicalResult parseCommaSeparatedList(llvm::cl::Option &opt, StringRef argName, StringRef optionStr, function_ref< LogicalResult(StringRef)> elementParseFn)
Parse a string containing a list of comma-delimited elements, invoking the given parser for each sub-...
Detect if any of the given parameter types has a sub-element handler.
llvm::PointerUnion< NamedAttribute *, NamedTypeConstraint * > Argument
This header declares functions that assit transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
LogicalResult parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, const ParserConfig &config, AsmParserState *asmState=nullptr, AsmParserCodeCompleteContext *codeCompleteContext=nullptr)
This parses the file specified by the indicated SourceMgr and appends parsed operations to the given ...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Attribute parseAttribute(llvm::StringRef attrStr, MLIRContext *context, Type type={}, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR attribute to an MLIR context if it was valid.
Type parseType(llvm::StringRef typeStr, MLIRContext *context, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR type to an MLIR context if it was valid.
AsmResourceEntryKind
This enum represents the different kinds of resource values.
@ Blob
A blob of data with an accompanying alignment.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
void addRegions(MutableArrayRef< std::unique_ptr< Region >> regions)
Take ownership of a set of regions that should be attached to the Operation.
SmallVector< Value, 4 > operands
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addSuccessors(Block *successor)
void addTypes(ArrayRef< Type > newTypes)
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
This class refers to all of the state maintained globally by the parser, such as the current lexer po...
SymbolState & symbols
The current state for symbol parsing.
const ParserConfig & config
The configuration used to setup the parser.
Lexer lex
The lexer for the source file we're parsing.
Token curToken
This is the next token that hasn't been consumed yet.
AsmParserCodeCompleteContext * codeCompleteContext
An optional code completion context.
AsmParserState * asmState
An optional pointer to a struct containing high level parser state to be populated during parsing.
SmallVector< StringRef > defaultDialectStack
This class contains record of any parsed top-level symbols.
llvm::StringMap< Attribute > attributeAliasDefinitions
A map from attribute alias identifier to Attribute.
DenseMap< const OpAsmDialectInterface *, llvm::StringMap< std::pair< std::string, AsmDialectResourceHandle > > > dialectResources
A map of dialect resource keys to the resolved resource name and handle to use during parsing.
llvm::StringMap< Type > typeAliasDefinitions
A map from type alias identifier to Type.