38 #include "llvm/ADT/APFloat.h"
39 #include "llvm/ADT/DenseMap.h"
40 #include "llvm/ADT/PointerUnion.h"
41 #include "llvm/ADT/STLExtras.h"
42 #include "llvm/ADT/ScopeExit.h"
43 #include "llvm/ADT/Sequence.h"
44 #include "llvm/ADT/StringExtras.h"
45 #include "llvm/ADT/StringMap.h"
46 #include "llvm/ADT/StringSet.h"
47 #include "llvm/Support/Alignment.h"
48 #include "llvm/Support/Casting.h"
49 #include "llvm/Support/Endian.h"
50 #include "llvm/Support/ErrorHandling.h"
51 #include "llvm/Support/MathExtras.h"
52 #include "llvm/Support/PrettyStackTrace.h"
53 #include "llvm/Support/SourceMgr.h"
54 #include "llvm/Support/raw_ostream.h"
86 StringRef contextMessage) {
91 if (
getToken().isNot(Token::l_paren))
95 if (
parseToken(Token::l_paren,
"expected '('" + contextMessage))
107 if (
parseToken(Token::less,
"expected '<'" + contextMessage))
114 if (
getToken().isNot(Token::l_square))
118 if (
parseToken(Token::l_square,
"expected '['" + contextMessage))
125 if (
getToken().isNot(Token::l_brace))
129 if (
parseToken(Token::l_brace,
"expected '{'" + contextMessage))
138 if (parseElementFn())
143 if (parseElementFn())
152 return parseToken(Token::r_paren,
"expected ')'" + contextMessage);
155 return parseToken(Token::greater,
"expected '>'" + contextMessage);
158 return parseToken(Token::r_square,
"expected ']'" + contextMessage);
161 return parseToken(Token::r_brace,
"expected '}'" + contextMessage);
163 llvm_unreachable(
"Unknown delimiter");
175 bool allowEmptyList) {
198 return emitError(SMLoc::getFromPointer(loc.getPointer() - 1), message);
220 loc = SMLoc::getFromPointer(loc.getPointer() - 1);
223 auto originalLoc = loc;
227 const char *curPtr = loc.getPointer();
231 StringRef startOfBuffer(bufferStart, curPtr - bufferStart);
236 startOfBuffer = startOfBuffer.rtrim(
" \t");
240 if (startOfBuffer.empty())
244 if (startOfBuffer.back() !=
'\n' && startOfBuffer.back() !=
'\r')
245 return emitError(SMLoc::getFromPointer(startOfBuffer.end()), message);
248 startOfBuffer = startOfBuffer.drop_back();
253 auto prevLine = startOfBuffer;
254 size_t newLineIndex = prevLine.find_last_of(
"\n\r");
255 if (newLineIndex != StringRef::npos)
256 prevLine = prevLine.drop_front(newLineIndex);
259 size_t commentStart = prevLine.find(
"//");
260 if (commentStart != StringRef::npos)
261 startOfBuffer = startOfBuffer.drop_back(prevLine.size() - commentStart);
268 const Twine &message) {
287 if (curToken.
isNot(Token::integer, Token::minus))
292 if (
parseToken(Token::integer,
"expected integer value"))
296 bool isHex = spelling.size() > 1 && spelling[1] ==
'x';
297 if (spelling.getAsInteger(isHex ? 0 : 10, result))
301 if (result.isNegative())
302 result = result.zext(result.getBitWidth() + 1);
314 if (curToken.
isNot(Token::integer, Token::minus)) {
320 if (
parseToken(Token::integer,
"expected integer value")) {
328 if (spelling[0] ==
'0' && spelling.size() > 1 &&
336 if (spelling.getAsInteger(10, result))
340 if (result.isNegative())
341 result = result.zext(result.getBitWidth() + 1);
351 const Token &tok,
bool isNegative,
352 const llvm::fltSemantics &semantics) {
354 if (tok.
is(Token::floatliteral)) {
359 result.emplace(isNegative ? -*val : *val);
361 result->convert(semantics, APFloat::rmNearestTiesToEven, &unused);
366 if (tok.
is(Token::integer))
375 const Token &tok,
bool isNegative,
376 const llvm::fltSemantics &semantics) {
378 bool isHex = spelling.size() > 1 && spelling[1] ==
'x';
380 return emitError(tok.
getLoc(),
"unexpected decimal integer literal for a "
381 "floating point value")
383 <<
"add a trailing dot to make the literal a float";
387 "hexadecimal float literal should not have a "
392 tok.
getSpelling().getAsInteger(isHex ? 0 : 10, intValue);
393 auto typeSizeInBits = APFloat::semanticsSizeInBits(semantics);
394 if (intValue.getActiveBits() > typeSizeInBits) {
396 "hexadecimal float constant out of range for type");
399 APInt truncatedValue(typeSizeInBits, intValue.getNumWords(),
400 intValue.getRawData());
401 result.emplace(semantics, truncatedValue);
418 FailureOr<AsmDialectResourceHandle>
421 assert(dialect &&
"expected valid dialect interface");
424 return emitError(
"expected identifier key for 'resource' entry");
430 std::pair<std::string, AsmDialectResourceHandle> &entry =
431 resources[dialect][name];
432 if (entry.first.empty()) {
433 FailureOr<AsmDialectResourceHandle> result = dialect->
declareResource(name);
434 if (failed(result)) {
436 <<
"unknown 'resource' key '" << name <<
"' for dialect '"
437 << dialect->getDialect()->getNamespace() <<
"'";
440 entry.second = *result;
447 FailureOr<AsmDialectResourceHandle>
452 <<
"' does not expect resource handles";
454 StringRef resourceName;
470 if (dialectName.empty() || dialectName.contains(
'.'))
481 auto shouldIgnoreOpCompletion = [&]() {
483 const char *it = loc.getPointer() - 1;
484 for (; it > bufBegin && *it !=
'\n'; --it)
485 if (!StringRef(
" \t\r").contains(*it))
489 if (shouldIgnoreOpCompletion())
507 if (name.consume_back(
"."))
548 class OperationParser :
public Parser {
550 OperationParser(
ParserState &state, ModuleOp topLevelOp);
555 ParseResult finalize();
564 struct DeferredLocInfo {
566 StringRef identifier;
570 void pushSSANameScope(
bool isIsolated);
573 ParseResult popSSANameScope();
576 ParseResult addDefinition(UnresolvedOperand useInfo,
Value value);
584 ParseResult parseSSAUse(UnresolvedOperand &result,
585 bool allowResultNumber =
true);
589 Value resolveSSAUse(UnresolvedOperand useInfo,
Type type);
591 ParseResult parseSSADefOrUseAndType(
598 std::optional<SMLoc> getReferenceLoc(StringRef name,
unsigned number) {
599 auto &values = isolatedNameScopes.back().values;
600 if (!values.count(name) || number >= values[name].size())
602 if (values[name][number].value)
603 return values[name][number].loc;
612 ParseResult parseOperation();
615 ParseResult parseSuccessor(
Block *&dest);
628 ParseResult parseGenericOperationAfterOpName(
633 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
636 std::optional<Attribute> propertiesAttribute = std::nullopt,
637 std::optional<FunctionType> parsedFnType = std::nullopt);
654 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument);
664 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>;
672 FailureOr<OperationName> parseCustomOperationName();
682 bool isIsolatedNameScope =
false);
685 ParseResult parseRegionBody(
Region ®ion, SMLoc startLoc,
687 bool isIsolatedNameScope);
694 ParseResult parseBlock(
Block *&block);
697 ParseResult parseBlockBody(
Block *block);
700 ParseResult parseOptionalBlockArgList(
Block *owner);
705 Block *getBlockNamed(StringRef name, SMLoc loc);
715 ParseResult codeCompleteSSAUse();
716 ParseResult codeCompleteBlock();
720 struct BlockDefinition {
727 struct ValueDefinition {
735 BlockDefinition &getBlockInfoByName(StringRef name) {
736 return blocksByName.back()[name];
740 void insertForwardRef(
Block *block, SMLoc loc) {
741 forwardRef.back().try_emplace(block, loc);
745 bool eraseForwardRef(
Block *block) {
return forwardRef.back().erase(block); }
748 void recordDefinition(StringRef def);
755 Value createForwardRefPlaceholder(SMLoc loc,
Type type);
758 bool isForwardRefPlaceholder(
Value value) {
759 return forwardRefPlaceholders.count(value);
766 struct IsolatedSSANameScope {
768 void recordDefinition(StringRef def) {
769 definitionsPerScope.back().insert(def);
773 void pushSSANameScope() { definitionsPerScope.push_back({}); }
776 void popSSANameScope() {
777 for (
auto &def : definitionsPerScope.pop_back_val())
778 values.erase(def.getKey());
783 llvm::StringMap<SmallVector<ValueDefinition, 1>> values;
805 std::vector<DeferredLocInfo> deferredLocsReferences;
818 OperationParser::OperationParser(
ParserState &state, ModuleOp topLevelOp)
819 :
Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) {
821 pushSSANameScope(
true);
828 OperationParser::~OperationParser() {
829 for (
auto &fwd : forwardRefPlaceholders) {
832 fwd.first.dropAllUses();
833 fwd.first.getDefiningOp()->destroy();
835 for (
const auto &scope : forwardRef) {
836 for (
const auto &fwd : scope) {
839 fwd.first->dropAllUses();
847 ParseResult OperationParser::finalize() {
850 if (!forwardRefPlaceholders.empty()) {
853 for (
auto entry : forwardRefPlaceholders)
854 errors.push_back(entry.second.getPointer());
855 llvm::array_pod_sort(errors.begin(), errors.end());
857 for (
const char *entry : errors) {
858 auto loc = SMLoc::getFromPointer(entry);
859 emitError(loc,
"use of undeclared SSA value name");
865 auto &attributeAliases = state.symbols.attributeAliasDefinitions;
866 auto locID = TypeID::get<DeferredLocInfo *>();
867 auto resolveLocation = [&,
this](
auto &opOrArgument) -> LogicalResult {
868 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc());
869 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID)
871 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()];
872 Attribute attr = attributeAliases.lookup(locInfo.identifier);
875 <<
"operation location alias was never defined";
876 auto locAttr = dyn_cast<LocationAttr>(attr);
879 <<
"expected location, but found '" << attr <<
"'";
880 opOrArgument.setLoc(locAttr);
884 auto walkRes = topLevelOp->walk([&](
Operation *op) {
885 if (failed(resolveLocation(*op)))
888 for (
Block &block : region.getBlocks())
890 if (failed(resolveLocation(arg)))
894 if (walkRes.wasInterrupted())
898 if (failed(popSSANameScope()))
902 if (state.config.shouldVerifyAfterParse() && failed(
verify(topLevelOp)))
907 state.asmState->finalize(topLevelOp);
915 void OperationParser::pushSSANameScope(
bool isIsolated) {
921 isolatedNameScopes.push_back({});
922 isolatedNameScopes.back().pushSSANameScope();
925 ParseResult OperationParser::popSSANameScope() {
926 auto forwardRefInCurrentScope = forwardRef.pop_back_val();
929 if (!forwardRefInCurrentScope.empty()) {
932 for (
auto entry : forwardRefInCurrentScope) {
933 errors.push_back({entry.second.getPointer(), entry.first});
935 topLevelOp->getRegion(0).push_back(entry.first);
937 llvm::array_pod_sort(errors.begin(), errors.end());
939 for (
auto entry : errors) {
940 auto loc = SMLoc::getFromPointer(entry.first);
941 emitError(loc,
"reference to an undefined block");
948 auto ¤tNameScope = isolatedNameScopes.back();
949 if (currentNameScope.definitionsPerScope.size() == 1)
950 isolatedNameScopes.pop_back();
952 currentNameScope.popSSANameScope();
954 blocksByName.pop_back();
959 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo,
961 auto &entries = getSSAValueEntry(useInfo.name);
964 if (entries.size() <= useInfo.number)
965 entries.resize(useInfo.number + 1);
969 if (
auto existing = entries[useInfo.number].value) {
970 if (!isForwardRefPlaceholder(existing)) {
972 .
append(
"redefinition of SSA value '", useInfo.name,
"'")
973 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
974 .
append(
"previously defined here");
977 if (existing.getType() != value.
getType()) {
979 .
append(
"definition of SSA value '", useInfo.name,
"#",
980 useInfo.number,
"' has type ", value.
getType())
981 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
982 .
append(
"previously used here with type ", existing.getType());
988 existing.replaceAllUsesWith(value);
989 existing.getDefiningOp()->destroy();
990 forwardRefPlaceholders.erase(existing);
995 state.asmState->refineDefinition(existing, value);
999 entries[useInfo.number] = {value, useInfo.location};
1000 recordDefinition(useInfo.name);
1009 ParseResult OperationParser::parseOptionalSSAUseList(
1011 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1014 UnresolvedOperand result;
1015 if (parseSSAUse(result))
1017 results.push_back(result);
1026 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result,
1027 bool allowResultNumber) {
1028 if (getToken().isCodeCompletion())
1029 return codeCompleteSSAUse();
1031 result.name = getTokenSpelling();
1033 result.location = getToken().getLoc();
1034 if (parseToken(Token::percent_identifier,
"expected SSA operand"))
1038 if (getToken().is(Token::hash_identifier)) {
1039 if (!allowResultNumber)
1040 return emitError(
"result number not allowed in argument list");
1042 if (
auto value = getToken().getHashIdentifierNumber())
1043 result.number = *value;
1045 return emitError(
"invalid SSA value result number");
1046 consumeToken(Token::hash_identifier);
1054 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo,
Type type) {
1055 auto &entries = getSSAValueEntry(useInfo.name);
1059 auto maybeRecordUse = [&](
Value value) {
1061 state.asmState->addUses(value, useInfo.location);
1066 if (useInfo.number < entries.size() && entries[useInfo.number].value) {
1067 Value result = entries[useInfo.number].value;
1070 return maybeRecordUse(result);
1072 emitError(useInfo.location,
"use of value '")
1074 "' expects different type than prior uses: ", type,
" vs ",
1076 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
1077 .
append(
"prior use here");
1082 if (entries.size() <= useInfo.number)
1083 entries.resize(useInfo.number + 1);
1087 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value))
1088 return (
emitError(useInfo.location,
"reference to invalid result number"),
1093 Value result = createForwardRefPlaceholder(useInfo.location, type);
1094 entries[useInfo.number] = {result, useInfo.location};
1095 return maybeRecordUse(result);
1101 ParseResult OperationParser::parseSSADefOrUseAndType(
1103 UnresolvedOperand useInfo;
1104 if (parseSSAUse(useInfo) ||
1105 parseToken(Token::colon,
"expected ':' and type for SSA operand"))
1112 return action(useInfo, type);
1121 ParseResult OperationParser::parseOptionalSSAUseAndTypeList(
1124 if (parseOptionalSSAUseList(valueIDs))
1128 if (valueIDs.empty())
1132 if (parseToken(Token::colon,
"expected ':' in operand list") ||
1133 parseTypeListNoParens(types))
1136 if (valueIDs.size() != types.size())
1138 << valueIDs.size() <<
" types to match operand list";
1140 results.reserve(valueIDs.size());
1141 for (
unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1142 if (
auto value = resolveSSAUse(valueIDs[i], types[i]))
1143 results.push_back(value);
1152 void OperationParser::recordDefinition(StringRef def) {
1153 isolatedNameScopes.back().recordDefinition(def);
1157 auto OperationParser::getSSAValueEntry(StringRef name)
1159 return isolatedNameScopes.back().values[name];
1163 Value OperationParser::createForwardRefPlaceholder(SMLoc loc,
Type type) {
1172 getEncodedSourceLocation(loc), name, type, {},
1173 std::nullopt,
nullptr, {},
1175 forwardRefPlaceholders[op->
getResult(0)] = loc;
1195 ParseResult OperationParser::parseOperation() {
1196 auto loc = getToken().
getLoc();
1198 size_t numExpectedResults = 0;
1199 if (getToken().is(Token::percent_identifier)) {
1201 auto parseNextResult = [&]() -> ParseResult {
1203 Token nameTok = getToken();
1204 if (parseToken(Token::percent_identifier,
1205 "expected valid ssa identifier"))
1209 size_t expectedSubResults = 1;
1210 if (consumeIf(Token::colon)) {
1212 if (!getToken().is(Token::integer))
1213 return emitWrongTokenError(
"expected integer number of results");
1216 auto val = getToken().getUInt64IntegerValue();
1217 if (!val || *val < 1)
1219 "expected named operation to have at least 1 result");
1220 consumeToken(Token::integer);
1221 expectedSubResults = *val;
1224 resultIDs.emplace_back(nameTok.
getSpelling(), expectedSubResults,
1226 numExpectedResults += expectedSubResults;
1232 if (parseToken(Token::equal,
"expected '=' after SSA name"))
1237 Token nameTok = getToken();
1238 if (nameTok.
is(Token::bare_identifier) || nameTok.
isKeyword())
1239 op = parseCustomOperation(resultIDs);
1240 else if (nameTok.
is(Token::string))
1241 op = parseGenericOperation();
1243 return codeCompleteStringDialectOrOperationName(nameTok.
getStringValue());
1245 return codeCompleteDialectOrElidedOpName(loc);
1247 return emitWrongTokenError(
"expected operation name in quotes");
1254 if (!resultIDs.empty()) {
1256 return emitError(loc,
"cannot name an operation with no results");
1258 return emitError(loc,
"operation defines ")
1260 << numExpectedResults <<
" to bind";
1263 if (state.asmState) {
1264 unsigned resultIt = 0;
1266 asmResultGroups.reserve(resultIDs.size());
1267 for (ResultRecord &record : resultIDs) {
1268 asmResultGroups.emplace_back(resultIt, std::get<2>(record));
1269 resultIt += std::get<1>(record);
1271 state.asmState->finalizeOperationDefinition(
1272 op, nameTok.
getLocRange(), getLastToken().getEndLoc(),
1277 unsigned opResI = 0;
1278 for (ResultRecord &resIt : resultIDs) {
1279 for (
unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) {
1280 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes},
1287 }
else if (state.asmState) {
1288 state.asmState->finalizeOperationDefinition(
1290 getLastToken().getEndLoc());
1300 ParseResult OperationParser::parseSuccessor(
Block *&dest) {
1301 if (getToken().isCodeCompletion())
1302 return codeCompleteBlock();
1305 if (!getToken().is(Token::caret_identifier))
1306 return emitWrongTokenError(
"expected block name");
1307 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1318 if (parseToken(Token::l_square,
"expected '['"))
1321 auto parseElt = [
this, &destinations] {
1323 ParseResult res = parseSuccessor(dest);
1324 destinations.push_back(dest);
1327 return parseCommaSeparatedListUntil(Token::r_square, parseElt,
1336 struct CleanupOpStateRegions {
1337 ~CleanupOpStateRegions() {
1339 regionsToClean.reserve(state.regions.size());
1340 for (
auto ®ion : state.regions)
1342 for (
auto &block : *region)
1349 ParseResult OperationParser::parseGenericOperationAfterOpName(
1353 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1355 std::optional<Attribute> propertiesAttribute,
1356 std::optional<FunctionType> parsedFnType) {
1360 if (!parsedOperandUseInfo) {
1361 if (parseToken(Token::l_paren,
"expected '(' to start operand list") ||
1362 parseOptionalSSAUseList(opInfo) ||
1363 parseToken(Token::r_paren,
"expected ')' to end operand list")) {
1366 parsedOperandUseInfo = opInfo;
1370 if (!parsedSuccessors) {
1371 if (getToken().is(Token::l_square)) {
1374 return emitError(
"successors in non-terminator");
1377 if (parseSuccessors(successors))
1386 if (propertiesAttribute) {
1388 }
else if (consumeIf(Token::less)) {
1392 if (parseToken(Token::greater,
"expected '>' to close properties"))
1396 if (!parsedRegions) {
1397 if (consumeIf(Token::l_paren)) {
1401 if (parseRegion(*result.
regions.back(), {}))
1403 }
while (consumeIf(Token::comma));
1404 if (parseToken(Token::r_paren,
"expected ')' to end region list"))
1412 if (!parsedAttributes) {
1413 if (getToken().is(Token::l_brace)) {
1423 if (!parsedFnType) {
1424 if (parseToken(Token::colon,
"expected ':' followed by operation type"))
1427 typeLoc = getEncodedSourceLocation(getToken().getLoc());
1431 auto fnType = dyn_cast<FunctionType>(type);
1435 parsedFnType = fnType;
1438 result.
addTypes(parsedFnType->getResults());
1442 if (operandTypes.size() != parsedOperandUseInfo->size()) {
1443 auto plural =
"s"[parsedOperandUseInfo->size() == 1];
1445 << parsedOperandUseInfo->size() <<
" operand type" << plural
1446 <<
" but had " << operandTypes.size();
1450 for (
unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) {
1452 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i]));
1460 Operation *OperationParser::parseGenericOperation() {
1462 auto srcLocation = getEncodedSourceLocation(getToken().getLoc());
1464 std::string name = getToken().getStringValue();
1466 return (
emitError(
"empty operation name is invalid"),
nullptr);
1467 if (name.find(
'\0') != StringRef::npos)
1468 return (
emitError(
"null character not allowed in operation name"),
nullptr);
1470 consumeToken(Token::string);
1473 CleanupOpStateRegions guard{result};
1477 StringRef dialectName = StringRef(name).split(
'.').first;
1478 if (!
getContext()->getLoadedDialect(dialectName) &&
1479 !
getContext()->getOrLoadDialect(dialectName)) {
1480 if (!
getContext()->allowsUnregisteredDialects()) {
1483 emitError(
"operation being parsed with an unregistered dialect. If "
1484 "this is intended, please use -allow-unregistered-dialect "
1485 "with the MLIR tool used");
1496 state.asmState->startOperationDefinition(result.
name);
1498 if (parseGenericOperationAfterOpName(result))
1522 std::optional<RegisteredOperationName> info =
1525 if (failed(info->verifyInherentAttrs(result.
attributes, [&]() {
1526 return mlir::emitError(srcLocation) <<
"'" << name <<
"' op ";
1534 if (parseTrailingLocationSpecifier(op))
1542 << properties <<
" for op " << name <<
": ";
1551 Operation *OperationParser::parseGenericOperation(
Block *insertBlock,
1553 Token nameToken = getToken();
1556 opBuilder.setInsertionPoint(insertBlock, insertPt);
1557 Operation *op = parseGenericOperation();
1564 state.asmState->finalizeOperationDefinition(
1566 getLastToken().getEndLoc());
1571 class CustomOpAsmParser :
public AsmParserImpl<OpAsmParser> {
1576 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser)
1578 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove),
1579 opName(opName), parser(parser) {
1580 (void)isIsolatedFromAbove;
1586 if (parseAssembly(*
this, opState))
1592 std::optional<NamedAttribute> duplicate =
1595 return emitError(getNameLoc(),
"attribute '")
1596 << duplicate->getName().getValue()
1597 <<
"' occurs more than once in the attribute list";
1603 return parser.parseGenericOperation(insertBlock, insertPt);
1606 FailureOr<OperationName> parseCustomOperationName() final {
1607 return parser.parseCustomOperationName();
1610 ParseResult parseGenericOperationAfterOpName(
1614 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1616 std::optional<Attribute> parsedPropertiesAttribute,
1617 std::optional<FunctionType> parsedFnType)
final {
1618 return parser.parseGenericOperationAfterOpName(
1619 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
1620 parsedAttributes, parsedPropertiesAttribute, parsedFnType);
1635 std::pair<StringRef, unsigned>
1636 getResultName(
unsigned resultNo)
const override {
1638 for (
const auto &entry : resultIDs) {
1639 if (resultNo < std::get<1>(entry)) {
1641 StringRef name = std::get<0>(entry).drop_front();
1642 return {name, resultNo};
1644 resultNo -= std::get<1>(entry);
1653 size_t getNumResults()
const override {
1655 for (
auto &entry : resultIDs)
1656 count += std::get<1>(entry);
1671 ParseResult parseOperand(UnresolvedOperand &result,
1672 bool allowResultNumber =
true)
override {
1674 if (parser.parseSSAUse(useInfo, allowResultNumber))
1683 parseOptionalOperand(UnresolvedOperand &result,
1684 bool allowResultNumber =
true)
override {
1685 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1686 return parseOperand(result, allowResultNumber);
1687 return std::nullopt;
1694 bool allowResultNumber =
true,
1695 int requiredOperandCount = -1)
override {
1700 Token tok = parser.getToken();
1704 if (requiredOperandCount == -1 || requiredOperandCount == 0)
1708 if (tok.
isAny(Token::l_paren, Token::l_square))
1709 return parser.emitError(
"unexpected delimiter");
1710 return parser.emitWrongTokenError(
"expected operand");
1714 auto parseOneOperand = [&]() -> ParseResult {
1715 return parseOperand(result.emplace_back(), allowResultNumber);
1718 auto startLoc = parser.getToken().getLoc();
1723 if (requiredOperandCount != -1 &&
1724 result.size() !=
static_cast<size_t>(requiredOperandCount))
1726 << requiredOperandCount <<
" operands";
1731 ParseResult resolveOperand(
const UnresolvedOperand &operand,
Type type,
1733 if (
auto value = parser.resolveSSAUse(operand, type)) {
1734 result.push_back(value);
1748 auto parseElement = [&](
bool isSymbol) -> ParseResult {
1749 UnresolvedOperand operand;
1750 if (parseOperand(operand))
1753 symOperands.push_back(operand);
1755 dimOperands.push_back(operand);
1760 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter))
1765 attrs.
push_back(parser.builder.getNamedAttr(attrName, mapAttr));
1769 operands.assign(dimOperands.begin(), dimOperands.end());
1770 operands.append(symOperands.begin(), symOperands.end());
1779 auto parseElement = [&](
bool isSymbol) -> ParseResult {
1780 UnresolvedOperand operand;
1781 if (parseOperand(operand))
1784 symbOperands.push_back(operand);
1786 dimOperands.push_back(operand);
1790 return parser.parseAffineExprOfSSAIds(expr, parseElement);
1803 ParseResult parseArgument(Argument &result,
bool allowType =
false,
1804 bool allowAttrs =
false)
override {
1806 if (parseOperand(result.ssaName,
false) ||
1807 (allowType && parseColonType(result.type)) ||
1808 (allowAttrs && parseOptionalAttrDict(attrs)) ||
1809 parseOptionalLocationSpecifier(result.sourceLoc))
1817 bool allowAttrs)
override {
1818 if (parser.getToken().is(Token::percent_identifier))
1819 return parseArgument(result, allowType, allowAttrs);
1820 return std::nullopt;
1824 Delimiter delimiter,
bool allowType,
1825 bool allowAttrs)
override {
1828 parser.getToken().isNot(Token::percent_identifier))
1831 auto parseOneArgument = [&]() -> ParseResult {
1832 return parseArgument(result.emplace_back(), allowType, allowAttrs);
1835 " in argument list");
1845 bool enableNameShadowing)
override {
1847 (void)isIsolatedFromAbove;
1848 assert((!enableNameShadowing || isIsolatedFromAbove) &&
1849 "name shadowing is only allowed on isolated regions");
1850 if (parser.parseRegion(region, arguments, enableNameShadowing))
1858 bool enableNameShadowing)
override {
1859 if (parser.getToken().isNot(Token::l_brace))
1860 return std::nullopt;
1861 return parseRegion(region, arguments, enableNameShadowing);
1868 parseOptionalRegion(std::unique_ptr<Region> ®ion,
1870 bool enableNameShadowing =
false)
override {
1871 if (parser.getToken().isNot(Token::l_brace))
1872 return std::nullopt;
1873 std::unique_ptr<Region> newRegion = std::make_unique<Region>();
1874 if (parseRegion(*newRegion, arguments, enableNameShadowing))
1877 region = std::move(newRegion);
1886 ParseResult parseSuccessor(
Block *&dest)
override {
1887 return parser.parseSuccessor(dest);
1892 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier))
1893 return std::nullopt;
1894 return parseSuccessor(dest);
1899 parseSuccessorAndUseList(
Block *&dest,
1901 if (parseSuccessor(dest))
1905 if (succeeded(parseOptionalLParen()) &&
1906 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) {
1921 if (failed(parseOptionalLParen()))
1922 return std::nullopt;
1924 auto parseElt = [&]() -> ParseResult {
1925 if (parseArgument(lhs.emplace_back()) || parseEqual() ||
1926 parseOperand(rhs.emplace_back()))
1930 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt);
1935 parseOptionalLocationSpecifier(std::optional<Location> &result)
override {
1937 if (!parser.consumeIf(Token::kw_loc))
1940 if (parser.parseToken(Token::l_paren,
"expected '(' in location"))
1943 Token tok = parser.getToken();
1949 if (tok.
is(Token::hash_identifier) && !tok.
getSpelling().contains(
'.')) {
1950 if (parser.parseLocationAlias(directLoc))
1952 }
else if (parser.parseLocationInstance(directLoc)) {
1956 if (parser.parseToken(Token::r_paren,
"expected ')' in location"))
1969 bool isIsolatedFromAbove;
1973 OperationParser &parser;
1977 FailureOr<OperationName> OperationParser::parseCustomOperationName() {
1978 Token nameTok = getToken();
1981 return (
emitError(
"empty operation name is invalid"), failure());
1985 std::optional<RegisteredOperationName> opInfo =
1992 auto opNameSplit = opName.split(
'.');
1993 StringRef dialectName = opNameSplit.first;
1994 std::string opNameStorage;
1995 if (opNameSplit.second.empty()) {
1997 if (getToken().isCodeCompletion() && opName.back() ==
'.')
1998 return codeCompleteOperationName(dialectName);
2000 dialectName = getState().defaultDialectStack.back();
2001 opNameStorage = (dialectName +
"." + opName).str();
2002 opName = opNameStorage;
2013 SMLoc opLoc = getToken().
getLoc();
2014 StringRef originalOpName = getTokenSpelling();
2016 FailureOr<OperationName> opNameInfo = parseCustomOperationName();
2017 if (failed(opNameInfo))
2019 StringRef opName = opNameInfo->getStringRef();
2025 bool isIsolatedFromAbove =
false;
2027 StringRef defaultDialect =
"";
2028 if (
auto opInfo = opNameInfo->getRegisteredInfo()) {
2029 parseAssemblyFn = opInfo->getParseAssemblyFn();
2031 auto *iface = opInfo->getInterface<OpAsmOpInterface>();
2032 if (iface && !iface->getDefaultDialect().empty())
2033 defaultDialect = iface->getDefaultDialect();
2035 std::optional<Dialect::ParseOpHook> dialectHook;
2036 Dialect *dialect = opNameInfo->getDialect();
2039 emitError(opLoc) <<
"Dialect `" << opNameInfo->getDialectNamespace()
2040 <<
"' not found for custom op '" << originalOpName
2042 if (originalOpName != opName)
2043 diag <<
" (tried '" << opName <<
"' as well)";
2044 auto ¬e =
diag.attachNote();
2045 note <<
"Registered dialects: ";
2046 llvm::interleaveComma(
getContext()->getAvailableDialects(), note,
2047 [&](StringRef dialect) { note << dialect; });
2048 note <<
" ; for more info on dialect registration see "
2049 "https://mlir.llvm.org/getting_started/Faq/"
2050 "#registered-loaded-dependent-whats-up-with-dialects-management";
2056 emitError(opLoc) <<
"custom op '" << originalOpName <<
"' is unknown";
2057 if (originalOpName != opName)
2058 diag <<
" (tried '" << opName <<
"' as well)";
2061 parseAssemblyFn = *dialectHook;
2063 getState().defaultDialectStack.push_back(defaultDialect);
2064 auto restoreDefaultDialect = llvm::make_scope_exit(
2065 [&]() { getState().defaultDialectStack.pop_back(); });
2069 llvm::PrettyStackTraceFormat fmt(
"MLIR Parser: custom op parser '%s'",
2070 opNameInfo->getIdentifier().data());
2073 auto srcLocation = getEncodedSourceLocation(opLoc);
2078 state.asmState->startOperationDefinition(opState.
name);
2081 CleanupOpStateRegions guard{opState};
2082 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn,
2083 isIsolatedFromAbove, opName, *
this);
2084 if (opAsmParser.parseOperation(opState))
2088 if (opAsmParser.didEmitError())
2096 if (parseTrailingLocationSpecifier(op))
2112 ParseResult OperationParser::parseLocationAlias(
LocationAttr &loc) {
2113 Token tok = getToken();
2114 consumeToken(Token::hash_identifier);
2115 StringRef identifier = tok.
getSpelling().drop_front();
2116 assert(!identifier.contains(
'.') &&
2117 "unexpected dialect attribute token, expected alias");
2120 state.asmState->addAttrAliasUses(identifier, tok.
getLocRange());
2123 Attribute attr = state.symbols.attributeAliasDefinitions.lookup(identifier);
2125 if (!(loc = dyn_cast<LocationAttr>(attr)))
2127 <<
"expected location, but found '" << attr <<
"'";
2132 TypeID::get<DeferredLocInfo *>(),
2134 deferredLocsReferences.push_back(DeferredLocInfo{tok.
getLoc(), identifier});
2140 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) {
2142 if (!consumeIf(Token::kw_loc))
2144 if (parseToken(Token::l_paren,
"expected '(' in location"))
2146 Token tok = getToken();
2152 if (tok.
is(Token::hash_identifier) && !tok.
getSpelling().contains(
'.')) {
2153 if (parseLocationAlias(directLoc))
2155 }
else if (parseLocationInstance(directLoc)) {
2159 if (parseToken(Token::r_paren,
"expected ')' in location"))
2162 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(opOrArgument))
2173 ParseResult OperationParser::parseRegion(
Region ®ion,
2175 bool isIsolatedNameScope) {
2177 Token lBraceTok = getToken();
2178 if (parseToken(Token::l_brace,
"expected '{' to begin a region"))
2183 state.asmState->startRegionDefinition();
2186 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) &&
2187 parseRegionBody(region, lBraceTok.
getLoc(), entryArguments,
2188 isIsolatedNameScope)) {
2191 consumeToken(Token::r_brace);
2195 state.asmState->finalizeRegionDefinition();
2200 ParseResult OperationParser::parseRegionBody(
Region ®ion, SMLoc startLoc,
2202 bool isIsolatedNameScope) {
2203 auto currentPt = opBuilder.saveInsertionPoint();
2206 pushSSANameScope(isIsolatedNameScope);
2209 auto owningBlock = std::make_unique<Block>();
2210 Block *block = owningBlock.get();
2215 if (state.asmState && getToken().isNot(Token::caret_identifier))
2216 state.asmState->addDefinition(block, startLoc);
2219 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) {
2221 if (getToken().is(Token::caret_identifier))
2222 return emitError(
"invalid block name in region with named arguments");
2224 for (
auto &entryArg : entryArguments) {
2225 auto &argInfo = entryArg.ssaName;
2228 if (
auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) {
2229 return emitError(argInfo.location,
"region entry argument '" +
2231 "' is already in use")
2232 .
attachNote(getEncodedSourceLocation(*defLoc))
2233 <<
"previously referenced here";
2235 Location loc = entryArg.sourceLoc.has_value()
2236 ? *entryArg.sourceLoc
2237 : getEncodedSourceLocation(argInfo.location);
2242 state.asmState->addDefinition(arg, argInfo.location);
2245 if (addDefinition(argInfo, arg))
2250 if (parseBlock(block))
2254 if (!entryArguments.empty() &&
2256 return emitError(
"entry block arguments were already defined");
2260 region.
push_back(owningBlock.release());
2261 while (getToken().isNot(Token::r_brace)) {
2262 Block *newBlock =
nullptr;
2263 if (parseBlock(newBlock))
2269 if (popSSANameScope())
2273 opBuilder.restoreInsertionPoint(currentPt);
2288 ParseResult OperationParser::parseBlock(
Block *&block) {
2291 if (block && getToken().isNot(Token::caret_identifier))
2292 return parseBlockBody(block);
2294 SMLoc nameLoc = getToken().getLoc();
2295 auto name = getTokenSpelling();
2296 if (parseToken(Token::caret_identifier,
"expected block name"))
2300 auto &blockAndLoc = getBlockInfoByName(name);
2301 blockAndLoc.loc = nameLoc;
2306 std::unique_ptr<Block> inflightBlock;
2307 auto cleanupOnFailure = llvm::make_scope_exit([&] {
2309 inflightBlock->dropAllDefinedValueUses();
2314 if (!blockAndLoc.block) {
2316 blockAndLoc.block = block;
2318 inflightBlock = std::make_unique<Block>();
2319 blockAndLoc.block = inflightBlock.get();
2326 }
else if (!eraseForwardRef(blockAndLoc.block)) {
2327 return emitError(nameLoc,
"redefinition of block '") << name <<
"'";
2331 inflightBlock.reset(blockAndLoc.block);
2336 state.asmState->addDefinition(blockAndLoc.block, nameLoc);
2337 block = blockAndLoc.block;
2340 if (getToken().is(Token::l_paren))
2341 if (parseOptionalBlockArgList(block))
2343 if (parseToken(Token::colon,
"expected ':' after block name"))
2347 ParseResult res = parseBlockBody(block);
2352 (void)inflightBlock.release();
2356 ParseResult OperationParser::parseBlockBody(
Block *block) {
2358 opBuilder.setInsertionPointToEnd(block);
2361 while (getToken().isNot(Token::caret_identifier, Token::r_brace))
2362 if (parseOperation())
2371 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) {
2372 BlockDefinition &blockDef = getBlockInfoByName(name);
2373 if (!blockDef.block) {
2374 blockDef = {
new Block(), loc};
2375 insertForwardRef(blockDef.block, blockDef.loc);
2380 state.asmState->addUses(blockDef.block, loc);
2382 return blockDef.block;
2391 ParseResult OperationParser::parseOptionalBlockArgList(
Block *owner) {
2392 if (getToken().is(Token::r_brace))
2398 unsigned nextArgument = 0;
2401 return parseSSADefOrUseAndType(
2402 [&](UnresolvedOperand useInfo,
Type type) -> ParseResult {
2407 if (definingExistingArgs) {
2410 return emitError(
"too many arguments specified in argument list");
2415 return emitError(
"argument and block argument type mismatch");
2417 auto loc = getEncodedSourceLocation(useInfo.location);
2423 if (parseTrailingLocationSpecifier(arg))
2429 state.asmState->addDefinition(arg, useInfo.location);
2431 return addDefinition(useInfo, arg);
2440 ParseResult OperationParser::codeCompleteSSAUse() {
2441 for (IsolatedSSANameScope &scope : isolatedNameScopes) {
2442 for (
auto &it : scope.values) {
2443 if (it.second.empty())
2445 Value frontValue = it.second.front().value;
2447 std::string detailData;
2448 llvm::raw_string_ostream detailOS(detailData);
2452 if (
auto result = dyn_cast<OpResult>(frontValue)) {
2453 if (!forwardRefPlaceholders.count(result))
2454 detailOS << result.getOwner()->getName() <<
": ";
2456 detailOS <<
"arg #" << cast<BlockArgument>(frontValue).getArgNumber()
2461 detailOS << frontValue.
getType();
2466 if (it.second.size() > 1)
2467 detailOS <<
", ...";
2469 state.codeCompleteContext->appendSSAValueCompletion(
2470 it.getKey(), std::move(detailData));
2477 ParseResult OperationParser::codeCompleteBlock() {
2480 StringRef spelling = getTokenSpelling();
2481 if (!(spelling.empty() || spelling ==
"^"))
2484 for (
const auto &it : blocksByName.back())
2485 state.codeCompleteContext->appendBlockCompletion(it.getFirst());
2496 class TopLevelOperationParser :
public Parser {
2508 ParseResult parseAttributeAliasDef();
2514 ParseResult parseTypeAliasDef();
2520 ParseResult parseFileMetadataDictionary();
2523 ParseResult parseResourceFileMetadata(
2524 function_ref<ParseResult(StringRef, SMLoc)> parseBody);
2525 ParseResult parseDialectResourceFileMetadata();
2526 ParseResult parseExternalResourceFileMetadata();
2533 ParsedResourceEntry(StringRef key, SMLoc keyLoc,
Token value,
Parser &p)
2534 : key(key), keyLoc(keyLoc), value(value), p(p) {}
2535 ~ParsedResourceEntry()
override =
default;
2537 StringRef getKey() const final {
return key; }
2542 if (value.isAny(Token::kw_true, Token::kw_false))
2544 return value.getSpelling().starts_with(
"\"0x")
2549 FailureOr<bool> parseAsBool() const final {
2550 if (value.is(Token::kw_true))
2552 if (value.is(Token::kw_false))
2554 return p.emitError(value.getLoc(),
2555 "expected 'true' or 'false' value for key '" + key +
2559 FailureOr<std::string> parseAsString() const final {
2560 if (value.isNot(Token::string))
2561 return p.emitError(value.getLoc(),
2562 "expected string value for key '" + key +
"'");
2563 return value.getStringValue();
2566 FailureOr<AsmResourceBlob>
2567 parseAsBlob(BlobAllocatorFn allocator)
const final {
2571 std::optional<std::string> blobData =
2572 value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
2574 return p.emitError(value.getLoc(),
2575 "expected hex string blob for key '" + key +
"'");
2579 if (blobData->size() <
sizeof(uint32_t)) {
2580 return p.emitError(value.getLoc(),
2581 "expected hex string blob for key '" + key +
2582 "' to encode alignment in first 4 bytes");
2584 llvm::support::ulittle32_t align;
2585 memcpy(&align, blobData->data(),
sizeof(uint32_t));
2586 if (align && !llvm::isPowerOf2_32(align)) {
2587 return p.emitError(value.getLoc(),
2588 "expected hex string blob for key '" + key +
2589 "' to encode alignment in first 4 bytes, but got "
2590 "non-power-of-2 value: " +
2595 StringRef data = StringRef(*blobData).drop_front(
sizeof(uint32_t));
2602 assert(llvm::isAddrAligned(llvm::Align(align), blob.
getData().data()) &&
2604 "blob allocator did not return a properly aligned address");
2617 ParseResult TopLevelOperationParser::parseAttributeAliasDef() {
2618 assert(getToken().is(Token::hash_identifier));
2619 StringRef aliasName = getTokenSpelling().drop_front();
2622 if (state.symbols.attributeAliasDefinitions.count(aliasName) > 0)
2623 return emitError(
"redefinition of attribute alias id '" + aliasName +
"'");
2626 if (aliasName.contains(
'.'))
2627 return emitError(
"attribute names with a '.' are reserved for "
2628 "dialect-defined names");
2630 SMRange location = getToken().getLocRange();
2631 consumeToken(Token::hash_identifier);
2634 if (parseToken(Token::equal,
"expected '=' in attribute alias definition"))
2644 state.asmState->addAttrAliasDefinition(aliasName, location, attr);
2645 state.symbols.attributeAliasDefinitions[aliasName] = attr;
2649 ParseResult TopLevelOperationParser::parseTypeAliasDef() {
2650 assert(getToken().is(Token::exclamation_identifier));
2651 StringRef aliasName = getTokenSpelling().drop_front();
2654 if (state.symbols.typeAliasDefinitions.count(aliasName) > 0)
2655 return emitError(
"redefinition of type alias id '" + aliasName +
"'");
2658 if (aliasName.contains(
'.'))
2659 return emitError(
"type names with a '.' are reserved for "
2660 "dialect-defined names");
2662 SMRange location = getToken().getLocRange();
2663 consumeToken(Token::exclamation_identifier);
2666 if (parseToken(Token::equal,
"expected '=' in type alias definition"))
2676 state.asmState->addTypeAliasDefinition(aliasName, location, aliasedType);
2677 state.symbols.typeAliasDefinitions.try_emplace(aliasName, aliasedType);
2681 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() {
2682 consumeToken(Token::file_metadata_begin);
2683 return parseCommaSeparatedListUntil(
2684 Token::file_metadata_end, [&]() -> ParseResult {
2686 SMLoc keyLoc = getToken().getLoc();
2688 if (failed(parseOptionalKeyword(&key)))
2689 return emitError(
"expected identifier key in file "
2690 "metadata dictionary");
2691 if (parseToken(Token::colon,
"expected ':'"))
2695 if (key ==
"dialect_resources")
2696 return parseDialectResourceFileMetadata();
2697 if (key ==
"external_resources")
2698 return parseExternalResourceFileMetadata();
2699 return emitError(keyLoc,
"unknown key '" + key +
2700 "' in file metadata dictionary");
2704 ParseResult TopLevelOperationParser::parseResourceFileMetadata(
2705 function_ref<ParseResult(StringRef, SMLoc)> parseBody) {
2706 if (parseToken(Token::l_brace,
"expected '{'"))
2709 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2711 SMLoc nameLoc = getToken().getLoc();
2713 if (failed(parseOptionalKeyword(&name)))
2714 return emitError(
"expected identifier key for 'resource' entry");
2716 if (parseToken(Token::colon,
"expected ':'") ||
2717 parseToken(Token::l_brace,
"expected '{'"))
2719 return parseBody(name, nameLoc);
2723 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() {
2724 return parseResourceFileMetadata([&](StringRef name,
2725 SMLoc nameLoc) -> ParseResult {
2729 return emitError(nameLoc,
"dialect '" + name +
"' is unknown");
2730 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect);
2732 return emitError() <<
"unexpected 'resource' section for dialect '"
2736 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2738 SMLoc keyLoc = getToken().getLoc();
2740 if (failed(parseResourceHandle(handler, key)) ||
2741 parseToken(Token::colon,
"expected ':'"))
2743 Token valueTok = getToken();
2746 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2747 return handler->parseResource(entry);
2752 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() {
2753 return parseResourceFileMetadata([&](StringRef name,
2754 SMLoc nameLoc) -> ParseResult {
2760 <<
"ignoring unknown external resources for '" << name <<
"'";
2763 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2765 SMLoc keyLoc = getToken().getLoc();
2767 if (failed(parseOptionalKeyword(&key)))
2769 "expected identifier key for 'external_resources' entry");
2770 if (parseToken(Token::colon,
"expected ':'"))
2772 Token valueTok = getToken();
2777 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2787 OperationParser opParser(state, topLevelOp.get());
2789 switch (getToken().getKind()) {
2792 if (opParser.parseOperation())
2798 if (opParser.finalize())
2803 auto &parsedOps = topLevelOp->getBody()->getOperations();
2805 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(),
2817 case Token::hash_identifier:
2818 if (parseAttributeAliasDef())
2823 case Token::exclamation_identifier:
2824 if (parseTypeAliasDef())
2829 case Token::file_metadata_begin:
2830 if (parseFileMetadataDictionary())
2843 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2850 ParserState state(sourceMgr, config, aliasState, asmState,
2851 codeCompleteContext);
2852 return TopLevelOperationParser(state).parse(block, parserLoc);
static void toLower(char *token)
Helper to convert C-style strings (i.e., '\0' terminated) to lower case.
static MLIRContext * getContext(OpFoldResult val)
static std::string diag(const llvm::Value &value)
#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 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 initialize(Operation *topLevelOp)
Initialize the state in preparation for populating more parser state under the given top-level operat...
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.
This class represents a processed binary blob of data.
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
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
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.
void resetPointer(const char *newPointer)
Change the position of the lexer cursor.
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...
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
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.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &)> ParseAssemblyFn
std::optional< RegisteredOperationName > getRegisteredInfo() const
If this operation is registered, returns the registered information, std::nullopt otherwise.
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, OpaqueProperties properties, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
OperationName getName()
The name of an operation is the key identifier for it.
LogicalResult setPropertiesFromAttribute(Attribute attr, function_ref< InFlightDiagnostic()> emitError)
Set the properties from the provided attribute.
unsigned getNumResults()
Return the number of results held by this operation.
This class implements Optional functionality for ParseResult.
This class represents a configuration for the MLIR assembly parser.
MLIRContext * getContext() const
Return the MLIRContext to be used when parsing.
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 ...
std::optional< double > getFloatingPointValue() const
For a floatliteral token, return its value as a double.
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.
Location getLoc() const
Return the location 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 parseFloatFromLiteral(std::optional< APFloat > &result, const Token &tok, bool isNegative, const llvm::fltSemantics &semantics)
Parse a floating point value from a literal.
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)
OptionalParseResult parseOptionalDecimalInteger(APInt &result)
Parse an optional integer value only in decimal format from the stream.
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 codeCompleteOptionalTokens(ArrayRef< StringRef > tokens)
ParseResult parseFloatFromIntegerLiteral(std::optional< APFloat > &result, const Token &tok, bool isNegative, const llvm::fltSemantics &semantics)
Parse a floating point value from an integer literal token.
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-...
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
llvm::PointerUnion< NamedAttribute *, NamedProperty *, NamedTypeConstraint * > Argument
Include the generated interface declarations.
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.
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.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
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,...
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.
OpaqueProperties getRawProperties()
SmallVector< Value, 4 > operands
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
Attribute propertiesAttr
This Attribute is used to opaquely construct the properties of the operation.
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.
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.