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);
352 std::optional<APFloat> &result,
const Token &tok,
bool isNegative,
353 const llvm::fltSemantics &semantics,
size_t typeSizeInBits) {
356 bool isHex = spelling.size() > 1 && spelling[1] ==
'x';
358 return emitError(loc,
"unexpected decimal integer literal for a "
359 "floating point value")
361 <<
"add a trailing dot to make the literal a float";
364 return emitError(loc,
"hexadecimal float literal should not have a "
369 tok.
getSpelling().getAsInteger(isHex ? 0 : 10, intValue);
370 if (intValue.getActiveBits() > typeSizeInBits)
371 return emitError(loc,
"hexadecimal float constant out of range for type");
373 APInt truncatedValue(typeSizeInBits, intValue.getNumWords(),
374 intValue.getRawData());
376 result.emplace(semantics, truncatedValue);
394 FailureOr<AsmDialectResourceHandle>
397 assert(dialect &&
"expected valid dialect interface");
400 return emitError(
"expected identifier key for 'resource' entry");
406 std::pair<std::string, AsmDialectResourceHandle> &entry =
407 resources[dialect][name];
408 if (entry.first.empty()) {
409 FailureOr<AsmDialectResourceHandle> result = dialect->
declareResource(name);
410 if (failed(result)) {
412 <<
"unknown 'resource' key '" << name <<
"' for dialect '"
413 << dialect->getDialect()->getNamespace() <<
"'";
416 entry.second = *result;
423 FailureOr<AsmDialectResourceHandle>
428 <<
"' does not expect resource handles";
430 StringRef resourceName;
446 if (dialectName.empty() || dialectName.contains(
'.'))
457 auto shouldIgnoreOpCompletion = [&]() {
459 const char *it = loc.getPointer() - 1;
460 for (; it > bufBegin && *it !=
'\n'; --it)
461 if (!StringRef(
" \t\r").contains(*it))
465 if (shouldIgnoreOpCompletion())
483 if (name.consume_back(
"."))
524 class OperationParser :
public Parser {
526 OperationParser(
ParserState &state, ModuleOp topLevelOp);
531 ParseResult finalize();
540 struct DeferredLocInfo {
542 StringRef identifier;
546 void pushSSANameScope(
bool isIsolated);
549 ParseResult popSSANameScope();
552 ParseResult addDefinition(UnresolvedOperand useInfo,
Value value);
560 ParseResult parseSSAUse(UnresolvedOperand &result,
561 bool allowResultNumber =
true);
565 Value resolveSSAUse(UnresolvedOperand useInfo,
Type type);
567 ParseResult parseSSADefOrUseAndType(
574 std::optional<SMLoc> getReferenceLoc(StringRef name,
unsigned number) {
575 auto &values = isolatedNameScopes.back().values;
576 if (!values.count(name) || number >= values[name].size())
578 if (values[name][number].value)
579 return values[name][number].loc;
588 ParseResult parseOperation();
591 ParseResult parseSuccessor(
Block *&dest);
604 ParseResult parseGenericOperationAfterOpName(
609 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
612 std::optional<Attribute> propertiesAttribute = std::nullopt,
613 std::optional<FunctionType> parsedFnType = std::nullopt);
630 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument);
639 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>;
647 FailureOr<OperationName> parseCustomOperationName();
657 bool isIsolatedNameScope =
false);
660 ParseResult parseRegionBody(
Region ®ion, SMLoc startLoc,
662 bool isIsolatedNameScope);
669 ParseResult parseBlock(
Block *&block);
672 ParseResult parseBlockBody(
Block *block);
675 ParseResult parseOptionalBlockArgList(
Block *owner);
680 Block *getBlockNamed(StringRef name, SMLoc loc);
690 ParseResult codeCompleteSSAUse();
691 ParseResult codeCompleteBlock();
695 struct BlockDefinition {
702 struct ValueDefinition {
710 BlockDefinition &getBlockInfoByName(StringRef name) {
711 return blocksByName.back()[name];
715 void insertForwardRef(
Block *block, SMLoc loc) {
716 forwardRef.back().try_emplace(block, loc);
720 bool eraseForwardRef(
Block *block) {
return forwardRef.back().erase(block); }
723 void recordDefinition(StringRef def);
730 Value createForwardRefPlaceholder(SMLoc loc,
Type type);
733 bool isForwardRefPlaceholder(
Value value) {
734 return forwardRefPlaceholders.count(value);
741 struct IsolatedSSANameScope {
743 void recordDefinition(StringRef def) {
744 definitionsPerScope.back().insert(def);
748 void pushSSANameScope() { definitionsPerScope.push_back({}); }
751 void popSSANameScope() {
752 for (
auto &def : definitionsPerScope.pop_back_val())
753 values.erase(def.getKey());
758 llvm::StringMap<SmallVector<ValueDefinition, 1>> values;
780 std::vector<DeferredLocInfo> deferredLocsReferences;
793 OperationParser::OperationParser(
ParserState &state, ModuleOp topLevelOp)
794 :
Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) {
796 pushSSANameScope(
true);
803 OperationParser::~OperationParser() {
804 for (
auto &fwd : forwardRefPlaceholders) {
807 fwd.first.dropAllUses();
808 fwd.first.getDefiningOp()->destroy();
810 for (
const auto &scope : forwardRef) {
811 for (
const auto &fwd : scope) {
814 fwd.first->dropAllUses();
822 ParseResult OperationParser::finalize() {
825 if (!forwardRefPlaceholders.empty()) {
828 for (
auto entry : forwardRefPlaceholders)
829 errors.push_back(entry.second.getPointer());
830 llvm::array_pod_sort(errors.begin(), errors.end());
832 for (
const char *entry : errors) {
833 auto loc = SMLoc::getFromPointer(entry);
834 emitError(loc,
"use of undeclared SSA value name");
840 auto &attributeAliases = state.symbols.attributeAliasDefinitions;
841 auto locID = TypeID::get<DeferredLocInfo *>();
842 auto resolveLocation = [&,
this](
auto &opOrArgument) -> LogicalResult {
843 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc());
844 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID)
846 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()];
847 Attribute attr = attributeAliases.lookup(locInfo.identifier);
850 <<
"operation location alias was never defined";
851 auto locAttr = dyn_cast<LocationAttr>(attr);
854 <<
"expected location, but found '" << attr <<
"'";
855 opOrArgument.setLoc(locAttr);
859 auto walkRes = topLevelOp->walk([&](
Operation *op) {
860 if (failed(resolveLocation(*op)))
863 for (
Block &block : region.getBlocks())
865 if (failed(resolveLocation(arg)))
869 if (walkRes.wasInterrupted())
873 if (failed(popSSANameScope()))
877 if (state.config.shouldVerifyAfterParse() && failed(
verify(topLevelOp)))
882 state.asmState->finalize(topLevelOp);
890 void OperationParser::pushSSANameScope(
bool isIsolated) {
896 isolatedNameScopes.push_back({});
897 isolatedNameScopes.back().pushSSANameScope();
900 ParseResult OperationParser::popSSANameScope() {
901 auto forwardRefInCurrentScope = forwardRef.pop_back_val();
904 if (!forwardRefInCurrentScope.empty()) {
907 for (
auto entry : forwardRefInCurrentScope) {
908 errors.push_back({entry.second.getPointer(), entry.first});
910 topLevelOp->getRegion(0).push_back(entry.first);
912 llvm::array_pod_sort(errors.begin(), errors.end());
914 for (
auto entry : errors) {
915 auto loc = SMLoc::getFromPointer(entry.first);
916 emitError(loc,
"reference to an undefined block");
923 auto ¤tNameScope = isolatedNameScopes.back();
924 if (currentNameScope.definitionsPerScope.size() == 1)
925 isolatedNameScopes.pop_back();
927 currentNameScope.popSSANameScope();
929 blocksByName.pop_back();
934 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo,
936 auto &entries = getSSAValueEntry(useInfo.name);
939 if (entries.size() <= useInfo.number)
940 entries.resize(useInfo.number + 1);
944 if (
auto existing = entries[useInfo.number].value) {
945 if (!isForwardRefPlaceholder(existing)) {
947 .
append(
"redefinition of SSA value '", useInfo.name,
"'")
948 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
949 .
append(
"previously defined here");
952 if (existing.getType() != value.
getType()) {
954 .
append(
"definition of SSA value '", useInfo.name,
"#",
955 useInfo.number,
"' has type ", value.
getType())
956 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
957 .
append(
"previously used here with type ", existing.getType());
963 existing.replaceAllUsesWith(value);
964 existing.getDefiningOp()->destroy();
965 forwardRefPlaceholders.erase(existing);
970 state.asmState->refineDefinition(existing, value);
974 entries[useInfo.number] = {value, useInfo.location};
975 recordDefinition(useInfo.name);
984 ParseResult OperationParser::parseOptionalSSAUseList(
986 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
989 UnresolvedOperand result;
990 if (parseSSAUse(result))
992 results.push_back(result);
1001 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result,
1002 bool allowResultNumber) {
1003 if (getToken().isCodeCompletion())
1004 return codeCompleteSSAUse();
1006 result.name = getTokenSpelling();
1008 result.location = getToken().getLoc();
1009 if (parseToken(Token::percent_identifier,
"expected SSA operand"))
1013 if (getToken().is(Token::hash_identifier)) {
1014 if (!allowResultNumber)
1015 return emitError(
"result number not allowed in argument list");
1017 if (
auto value = getToken().getHashIdentifierNumber())
1018 result.number = *value;
1020 return emitError(
"invalid SSA value result number");
1021 consumeToken(Token::hash_identifier);
1029 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo,
Type type) {
1030 auto &entries = getSSAValueEntry(useInfo.name);
1034 auto maybeRecordUse = [&](
Value value) {
1036 state.asmState->addUses(value, useInfo.location);
1041 if (useInfo.number < entries.size() && entries[useInfo.number].value) {
1042 Value result = entries[useInfo.number].value;
1045 return maybeRecordUse(result);
1047 emitError(useInfo.location,
"use of value '")
1049 "' expects different type than prior uses: ", type,
" vs ",
1051 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
1052 .
append(
"prior use here");
1057 if (entries.size() <= useInfo.number)
1058 entries.resize(useInfo.number + 1);
1062 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value))
1063 return (
emitError(useInfo.location,
"reference to invalid result number"),
1068 Value result = createForwardRefPlaceholder(useInfo.location, type);
1069 entries[useInfo.number] = {result, useInfo.location};
1070 return maybeRecordUse(result);
1076 ParseResult OperationParser::parseSSADefOrUseAndType(
1078 UnresolvedOperand useInfo;
1079 if (parseSSAUse(useInfo) ||
1080 parseToken(Token::colon,
"expected ':' and type for SSA operand"))
1087 return action(useInfo, type);
1096 ParseResult OperationParser::parseOptionalSSAUseAndTypeList(
1099 if (parseOptionalSSAUseList(valueIDs))
1103 if (valueIDs.empty())
1107 if (parseToken(Token::colon,
"expected ':' in operand list") ||
1108 parseTypeListNoParens(types))
1111 if (valueIDs.size() != types.size())
1113 << valueIDs.size() <<
" types to match operand list";
1115 results.reserve(valueIDs.size());
1116 for (
unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1117 if (
auto value = resolveSSAUse(valueIDs[i], types[i]))
1118 results.push_back(value);
1127 void OperationParser::recordDefinition(StringRef def) {
1128 isolatedNameScopes.back().recordDefinition(def);
1132 auto OperationParser::getSSAValueEntry(StringRef name)
1134 return isolatedNameScopes.back().values[name];
1138 Value OperationParser::createForwardRefPlaceholder(SMLoc loc,
Type type) {
1147 getEncodedSourceLocation(loc), name, type, {},
1148 std::nullopt,
nullptr, {},
1150 forwardRefPlaceholders[op->
getResult(0)] = loc;
1170 ParseResult OperationParser::parseOperation() {
1171 auto loc = getToken().
getLoc();
1173 size_t numExpectedResults = 0;
1174 if (getToken().is(Token::percent_identifier)) {
1176 auto parseNextResult = [&]() -> ParseResult {
1178 Token nameTok = getToken();
1179 if (parseToken(Token::percent_identifier,
1180 "expected valid ssa identifier"))
1184 size_t expectedSubResults = 1;
1185 if (consumeIf(Token::colon)) {
1187 if (!getToken().is(Token::integer))
1188 return emitWrongTokenError(
"expected integer number of results");
1191 auto val = getToken().getUInt64IntegerValue();
1192 if (!val || *val < 1)
1194 "expected named operation to have at least 1 result");
1195 consumeToken(Token::integer);
1196 expectedSubResults = *val;
1199 resultIDs.emplace_back(nameTok.
getSpelling(), expectedSubResults,
1201 numExpectedResults += expectedSubResults;
1207 if (parseToken(Token::equal,
"expected '=' after SSA name"))
1212 Token nameTok = getToken();
1213 if (nameTok.
is(Token::bare_identifier) || nameTok.
isKeyword())
1214 op = parseCustomOperation(resultIDs);
1215 else if (nameTok.
is(Token::string))
1216 op = parseGenericOperation();
1218 return codeCompleteStringDialectOrOperationName(nameTok.
getStringValue());
1220 return codeCompleteDialectOrElidedOpName(loc);
1222 return emitWrongTokenError(
"expected operation name in quotes");
1229 if (!resultIDs.empty()) {
1231 return emitError(loc,
"cannot name an operation with no results");
1233 return emitError(loc,
"operation defines ")
1235 << numExpectedResults <<
" to bind";
1238 if (state.asmState) {
1239 unsigned resultIt = 0;
1241 asmResultGroups.reserve(resultIDs.size());
1242 for (ResultRecord &record : resultIDs) {
1243 asmResultGroups.emplace_back(resultIt, std::get<2>(record));
1244 resultIt += std::get<1>(record);
1246 state.asmState->finalizeOperationDefinition(
1247 op, nameTok.
getLocRange(), getLastToken().getEndLoc(),
1252 unsigned opResI = 0;
1253 for (ResultRecord &resIt : resultIDs) {
1254 for (
unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) {
1255 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes},
1262 }
else if (state.asmState) {
1263 state.asmState->finalizeOperationDefinition(
1265 getLastToken().getEndLoc());
1275 ParseResult OperationParser::parseSuccessor(
Block *&dest) {
1276 if (getToken().isCodeCompletion())
1277 return codeCompleteBlock();
1280 if (!getToken().is(Token::caret_identifier))
1281 return emitWrongTokenError(
"expected block name");
1282 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1293 if (parseToken(Token::l_square,
"expected '['"))
1296 auto parseElt = [
this, &destinations] {
1298 ParseResult res = parseSuccessor(dest);
1299 destinations.push_back(dest);
1302 return parseCommaSeparatedListUntil(Token::r_square, parseElt,
1311 struct CleanupOpStateRegions {
1312 ~CleanupOpStateRegions() {
1314 regionsToClean.reserve(state.regions.size());
1315 for (
auto ®ion : state.regions)
1317 for (
auto &block : *region)
1324 ParseResult OperationParser::parseGenericOperationAfterOpName(
1328 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1330 std::optional<Attribute> propertiesAttribute,
1331 std::optional<FunctionType> parsedFnType) {
1335 if (!parsedOperandUseInfo) {
1336 if (parseToken(Token::l_paren,
"expected '(' to start operand list") ||
1337 parseOptionalSSAUseList(opInfo) ||
1338 parseToken(Token::r_paren,
"expected ')' to end operand list")) {
1341 parsedOperandUseInfo = opInfo;
1345 if (!parsedSuccessors) {
1346 if (getToken().is(Token::l_square)) {
1349 return emitError(
"successors in non-terminator");
1352 if (parseSuccessors(successors))
1361 if (propertiesAttribute) {
1363 }
else if (consumeIf(Token::less)) {
1367 if (parseToken(Token::greater,
"expected '>' to close properties"))
1371 if (!parsedRegions) {
1372 if (consumeIf(Token::l_paren)) {
1376 if (parseRegion(*result.
regions.back(), {}))
1378 }
while (consumeIf(Token::comma));
1379 if (parseToken(Token::r_paren,
"expected ')' to end region list"))
1387 if (!parsedAttributes) {
1388 if (getToken().is(Token::l_brace)) {
1398 if (!parsedFnType) {
1399 if (parseToken(Token::colon,
"expected ':' followed by operation type"))
1402 typeLoc = getEncodedSourceLocation(getToken().getLoc());
1406 auto fnType = dyn_cast<FunctionType>(type);
1410 parsedFnType = fnType;
1413 result.
addTypes(parsedFnType->getResults());
1417 if (operandTypes.size() != parsedOperandUseInfo->size()) {
1418 auto plural =
"s"[parsedOperandUseInfo->size() == 1];
1420 << parsedOperandUseInfo->size() <<
" operand type" << plural
1421 <<
" but had " << operandTypes.size();
1425 for (
unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) {
1427 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i]));
1435 Operation *OperationParser::parseGenericOperation() {
1437 auto srcLocation = getEncodedSourceLocation(getToken().getLoc());
1439 std::string name = getToken().getStringValue();
1441 return (
emitError(
"empty operation name is invalid"),
nullptr);
1442 if (name.find(
'\0') != StringRef::npos)
1443 return (
emitError(
"null character not allowed in operation name"),
nullptr);
1445 consumeToken(Token::string);
1448 CleanupOpStateRegions guard{result};
1452 StringRef dialectName = StringRef(name).split(
'.').first;
1453 if (!
getContext()->getLoadedDialect(dialectName) &&
1454 !
getContext()->getOrLoadDialect(dialectName)) {
1455 if (!
getContext()->allowsUnregisteredDialects()) {
1458 emitError(
"operation being parsed with an unregistered dialect. If "
1459 "this is intended, please use -allow-unregistered-dialect "
1460 "with the MLIR tool used");
1471 state.asmState->startOperationDefinition(result.
name);
1473 if (parseGenericOperationAfterOpName(result))
1497 std::optional<RegisteredOperationName> info =
1500 if (failed(info->verifyInherentAttrs(result.
attributes, [&]() {
1501 return mlir::emitError(srcLocation) <<
"'" << name <<
"' op ";
1509 if (parseTrailingLocationSpecifier(op))
1517 << properties <<
" for op " << name <<
": ";
1526 Operation *OperationParser::parseGenericOperation(
Block *insertBlock,
1528 Token nameToken = getToken();
1531 opBuilder.setInsertionPoint(insertBlock, insertPt);
1532 Operation *op = parseGenericOperation();
1539 state.asmState->finalizeOperationDefinition(
1541 getLastToken().getEndLoc());
1546 class CustomOpAsmParser :
public AsmParserImpl<OpAsmParser> {
1551 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser)
1553 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove),
1554 opName(opName), parser(parser) {
1555 (void)isIsolatedFromAbove;
1561 if (parseAssembly(*
this, opState))
1567 std::optional<NamedAttribute> duplicate =
1570 return emitError(getNameLoc(),
"attribute '")
1571 << duplicate->getName().getValue()
1572 <<
"' occurs more than once in the attribute list";
1578 return parser.parseGenericOperation(insertBlock, insertPt);
1581 FailureOr<OperationName> parseCustomOperationName() final {
1582 return parser.parseCustomOperationName();
1585 ParseResult parseGenericOperationAfterOpName(
1589 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1591 std::optional<Attribute> parsedPropertiesAttribute,
1592 std::optional<FunctionType> parsedFnType)
final {
1593 return parser.parseGenericOperationAfterOpName(
1594 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
1595 parsedAttributes, parsedPropertiesAttribute, parsedFnType);
1610 std::pair<StringRef, unsigned>
1611 getResultName(
unsigned resultNo)
const override {
1613 for (
const auto &entry : resultIDs) {
1614 if (resultNo < std::get<1>(entry)) {
1616 StringRef name = std::get<0>(entry).drop_front();
1617 return {name, resultNo};
1619 resultNo -= std::get<1>(entry);
1628 size_t getNumResults()
const override {
1630 for (
auto &entry : resultIDs)
1631 count += std::get<1>(entry);
1646 ParseResult parseOperand(UnresolvedOperand &result,
1647 bool allowResultNumber =
true)
override {
1649 if (parser.parseSSAUse(useInfo, allowResultNumber))
1658 parseOptionalOperand(UnresolvedOperand &result,
1659 bool allowResultNumber =
true)
override {
1660 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1661 return parseOperand(result, allowResultNumber);
1662 return std::nullopt;
1669 bool allowResultNumber =
true,
1670 int requiredOperandCount = -1)
override {
1675 Token tok = parser.getToken();
1679 if (requiredOperandCount == -1 || requiredOperandCount == 0)
1683 if (tok.
isAny(Token::l_paren, Token::l_square))
1684 return parser.emitError(
"unexpected delimiter");
1685 return parser.emitWrongTokenError(
"expected operand");
1689 auto parseOneOperand = [&]() -> ParseResult {
1690 return parseOperand(result.emplace_back(), allowResultNumber);
1693 auto startLoc = parser.getToken().getLoc();
1698 if (requiredOperandCount != -1 &&
1699 result.size() !=
static_cast<size_t>(requiredOperandCount))
1701 << requiredOperandCount <<
" operands";
1706 ParseResult resolveOperand(
const UnresolvedOperand &operand,
Type type,
1708 if (
auto value = parser.resolveSSAUse(operand, type)) {
1709 result.push_back(value);
1723 auto parseElement = [&](
bool isSymbol) -> ParseResult {
1724 UnresolvedOperand operand;
1725 if (parseOperand(operand))
1728 symOperands.push_back(operand);
1730 dimOperands.push_back(operand);
1735 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter))
1740 attrs.
push_back(parser.builder.getNamedAttr(attrName, mapAttr));
1744 operands.assign(dimOperands.begin(), dimOperands.end());
1745 operands.append(symOperands.begin(), symOperands.end());
1754 auto parseElement = [&](
bool isSymbol) -> ParseResult {
1755 UnresolvedOperand operand;
1756 if (parseOperand(operand))
1759 symbOperands.push_back(operand);
1761 dimOperands.push_back(operand);
1765 return parser.parseAffineExprOfSSAIds(expr, parseElement);
1778 ParseResult parseArgument(Argument &result,
bool allowType =
false,
1779 bool allowAttrs =
false)
override {
1781 if (parseOperand(result.ssaName,
false) ||
1782 (allowType && parseColonType(result.type)) ||
1783 (allowAttrs && parseOptionalAttrDict(attrs)) ||
1784 parseOptionalLocationSpecifier(result.sourceLoc))
1792 bool allowAttrs)
override {
1793 if (parser.getToken().is(Token::percent_identifier))
1794 return parseArgument(result, allowType, allowAttrs);
1795 return std::nullopt;
1799 Delimiter delimiter,
bool allowType,
1800 bool allowAttrs)
override {
1803 parser.getToken().isNot(Token::percent_identifier))
1806 auto parseOneArgument = [&]() -> ParseResult {
1807 return parseArgument(result.emplace_back(), allowType, allowAttrs);
1810 " in argument list");
1820 bool enableNameShadowing)
override {
1822 (void)isIsolatedFromAbove;
1823 assert((!enableNameShadowing || isIsolatedFromAbove) &&
1824 "name shadowing is only allowed on isolated regions");
1825 if (parser.parseRegion(region, arguments, enableNameShadowing))
1833 bool enableNameShadowing)
override {
1834 if (parser.getToken().isNot(Token::l_brace))
1835 return std::nullopt;
1836 return parseRegion(region, arguments, enableNameShadowing);
1843 parseOptionalRegion(std::unique_ptr<Region> ®ion,
1845 bool enableNameShadowing =
false)
override {
1846 if (parser.getToken().isNot(Token::l_brace))
1847 return std::nullopt;
1848 std::unique_ptr<Region> newRegion = std::make_unique<Region>();
1849 if (parseRegion(*newRegion, arguments, enableNameShadowing))
1852 region = std::move(newRegion);
1861 ParseResult parseSuccessor(
Block *&dest)
override {
1862 return parser.parseSuccessor(dest);
1867 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier))
1868 return std::nullopt;
1869 return parseSuccessor(dest);
1874 parseSuccessorAndUseList(
Block *&dest,
1876 if (parseSuccessor(dest))
1880 if (succeeded(parseOptionalLParen()) &&
1881 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) {
1896 if (failed(parseOptionalLParen()))
1897 return std::nullopt;
1899 auto parseElt = [&]() -> ParseResult {
1900 if (parseArgument(lhs.emplace_back()) || parseEqual() ||
1901 parseOperand(rhs.emplace_back()))
1905 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt);
1910 parseOptionalLocationSpecifier(std::optional<Location> &result)
override {
1912 if (!parser.consumeIf(Token::kw_loc))
1915 if (parser.parseToken(Token::l_paren,
"expected '(' in location"))
1918 Token tok = parser.getToken();
1922 if (tok.
is(Token::hash_identifier)) {
1923 if (parser.parseLocationAlias(directLoc))
1925 }
else if (parser.parseLocationInstance(directLoc)) {
1929 if (parser.parseToken(Token::r_paren,
"expected ')' in location"))
1942 bool isIsolatedFromAbove;
1946 OperationParser &parser;
1950 FailureOr<OperationName> OperationParser::parseCustomOperationName() {
1951 Token nameTok = getToken();
1954 return (
emitError(
"empty operation name is invalid"), failure());
1958 std::optional<RegisteredOperationName> opInfo =
1965 auto opNameSplit = opName.split(
'.');
1966 StringRef dialectName = opNameSplit.first;
1967 std::string opNameStorage;
1968 if (opNameSplit.second.empty()) {
1970 if (getToken().isCodeCompletion() && opName.back() ==
'.')
1971 return codeCompleteOperationName(dialectName);
1973 dialectName = getState().defaultDialectStack.back();
1974 opNameStorage = (dialectName +
"." + opName).str();
1975 opName = opNameStorage;
1986 SMLoc opLoc = getToken().
getLoc();
1987 StringRef originalOpName = getTokenSpelling();
1989 FailureOr<OperationName> opNameInfo = parseCustomOperationName();
1990 if (failed(opNameInfo))
1992 StringRef opName = opNameInfo->getStringRef();
1998 bool isIsolatedFromAbove =
false;
2000 StringRef defaultDialect =
"";
2001 if (
auto opInfo = opNameInfo->getRegisteredInfo()) {
2002 parseAssemblyFn = opInfo->getParseAssemblyFn();
2004 auto *iface = opInfo->getInterface<OpAsmOpInterface>();
2005 if (iface && !iface->getDefaultDialect().empty())
2006 defaultDialect = iface->getDefaultDialect();
2008 std::optional<Dialect::ParseOpHook> dialectHook;
2009 Dialect *dialect = opNameInfo->getDialect();
2012 emitError(opLoc) <<
"Dialect `" << opNameInfo->getDialectNamespace()
2013 <<
"' not found for custom op '" << originalOpName
2015 if (originalOpName != opName)
2016 diag <<
" (tried '" << opName <<
"' as well)";
2017 auto ¬e =
diag.attachNote();
2018 note <<
"Registered dialects: ";
2019 llvm::interleaveComma(
getContext()->getAvailableDialects(), note,
2020 [&](StringRef dialect) { note << dialect; });
2021 note <<
" ; for more info on dialect registration see "
2022 "https://mlir.llvm.org/getting_started/Faq/"
2023 "#registered-loaded-dependent-whats-up-with-dialects-management";
2029 emitError(opLoc) <<
"custom op '" << originalOpName <<
"' is unknown";
2030 if (originalOpName != opName)
2031 diag <<
" (tried '" << opName <<
"' as well)";
2034 parseAssemblyFn = *dialectHook;
2036 getState().defaultDialectStack.push_back(defaultDialect);
2037 auto restoreDefaultDialect = llvm::make_scope_exit(
2038 [&]() { getState().defaultDialectStack.pop_back(); });
2042 llvm::PrettyStackTraceFormat fmt(
"MLIR Parser: custom op parser '%s'",
2043 opNameInfo->getIdentifier().data());
2046 auto srcLocation = getEncodedSourceLocation(opLoc);
2051 state.asmState->startOperationDefinition(opState.
name);
2054 CleanupOpStateRegions guard{opState};
2055 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn,
2056 isIsolatedFromAbove, opName, *
this);
2057 if (opAsmParser.parseOperation(opState))
2061 if (opAsmParser.didEmitError())
2069 if (parseTrailingLocationSpecifier(op))
2085 ParseResult OperationParser::parseLocationAlias(
LocationAttr &loc) {
2086 Token tok = getToken();
2087 consumeToken(Token::hash_identifier);
2088 StringRef identifier = tok.
getSpelling().drop_front();
2089 if (identifier.contains(
'.')) {
2091 <<
"expected location, but found dialect attribute: '#" << identifier
2095 state.asmState->addAttrAliasUses(identifier, tok.
getLocRange());
2098 Attribute attr = state.symbols.attributeAliasDefinitions.lookup(identifier);
2100 if (!(loc = dyn_cast<LocationAttr>(attr)))
2102 <<
"expected location, but found '" << attr <<
"'";
2107 TypeID::get<DeferredLocInfo *>(),
2109 deferredLocsReferences.push_back(DeferredLocInfo{tok.
getLoc(), identifier});
2115 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) {
2117 if (!consumeIf(Token::kw_loc))
2119 if (parseToken(Token::l_paren,
"expected '(' in location"))
2121 Token tok = getToken();
2126 if (tok.
is(Token::hash_identifier)) {
2127 if (parseLocationAlias(directLoc))
2129 }
else if (parseLocationInstance(directLoc)) {
2133 if (parseToken(Token::r_paren,
"expected ')' in location"))
2136 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(opOrArgument))
2147 ParseResult OperationParser::parseRegion(
Region ®ion,
2149 bool isIsolatedNameScope) {
2151 Token lBraceTok = getToken();
2152 if (parseToken(Token::l_brace,
"expected '{' to begin a region"))
2157 state.asmState->startRegionDefinition();
2160 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) &&
2161 parseRegionBody(region, lBraceTok.
getLoc(), entryArguments,
2162 isIsolatedNameScope)) {
2165 consumeToken(Token::r_brace);
2169 state.asmState->finalizeRegionDefinition();
2174 ParseResult OperationParser::parseRegionBody(
Region ®ion, SMLoc startLoc,
2176 bool isIsolatedNameScope) {
2177 auto currentPt = opBuilder.saveInsertionPoint();
2180 pushSSANameScope(isIsolatedNameScope);
2183 auto owningBlock = std::make_unique<Block>();
2184 Block *block = owningBlock.get();
2189 if (state.asmState && getToken().isNot(Token::caret_identifier))
2190 state.asmState->addDefinition(block, startLoc);
2193 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) {
2195 if (getToken().is(Token::caret_identifier))
2196 return emitError(
"invalid block name in region with named arguments");
2198 for (
auto &entryArg : entryArguments) {
2199 auto &argInfo = entryArg.ssaName;
2202 if (
auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) {
2203 return emitError(argInfo.location,
"region entry argument '" +
2205 "' is already in use")
2206 .
attachNote(getEncodedSourceLocation(*defLoc))
2207 <<
"previously referenced here";
2209 Location loc = entryArg.sourceLoc.has_value()
2210 ? *entryArg.sourceLoc
2211 : getEncodedSourceLocation(argInfo.location);
2216 state.asmState->addDefinition(arg, argInfo.location);
2219 if (addDefinition(argInfo, arg))
2224 if (parseBlock(block))
2228 if (!entryArguments.empty() &&
2230 return emitError(
"entry block arguments were already defined");
2234 region.
push_back(owningBlock.release());
2235 while (getToken().isNot(Token::r_brace)) {
2236 Block *newBlock =
nullptr;
2237 if (parseBlock(newBlock))
2243 if (popSSANameScope())
2247 opBuilder.restoreInsertionPoint(currentPt);
2262 ParseResult OperationParser::parseBlock(
Block *&block) {
2265 if (block && getToken().isNot(Token::caret_identifier))
2266 return parseBlockBody(block);
2268 SMLoc nameLoc = getToken().getLoc();
2269 auto name = getTokenSpelling();
2270 if (parseToken(Token::caret_identifier,
"expected block name"))
2274 auto &blockAndLoc = getBlockInfoByName(name);
2275 blockAndLoc.loc = nameLoc;
2280 std::unique_ptr<Block> inflightBlock;
2281 auto cleanupOnFailure = llvm::make_scope_exit([&] {
2283 inflightBlock->dropAllDefinedValueUses();
2288 if (!blockAndLoc.block) {
2290 blockAndLoc.block = block;
2292 inflightBlock = std::make_unique<Block>();
2293 blockAndLoc.block = inflightBlock.get();
2300 }
else if (!eraseForwardRef(blockAndLoc.block)) {
2301 return emitError(nameLoc,
"redefinition of block '") << name <<
"'";
2305 inflightBlock.reset(blockAndLoc.block);
2310 state.asmState->addDefinition(blockAndLoc.block, nameLoc);
2311 block = blockAndLoc.block;
2314 if (getToken().is(Token::l_paren))
2315 if (parseOptionalBlockArgList(block))
2317 if (parseToken(Token::colon,
"expected ':' after block name"))
2321 ParseResult res = parseBlockBody(block);
2326 (void)inflightBlock.release();
2330 ParseResult OperationParser::parseBlockBody(
Block *block) {
2332 opBuilder.setInsertionPointToEnd(block);
2335 while (getToken().isNot(Token::caret_identifier, Token::r_brace))
2336 if (parseOperation())
2345 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) {
2346 BlockDefinition &blockDef = getBlockInfoByName(name);
2347 if (!blockDef.block) {
2348 blockDef = {
new Block(), loc};
2349 insertForwardRef(blockDef.block, blockDef.loc);
2354 state.asmState->addUses(blockDef.block, loc);
2356 return blockDef.block;
2365 ParseResult OperationParser::parseOptionalBlockArgList(
Block *owner) {
2366 if (getToken().is(Token::r_brace))
2372 unsigned nextArgument = 0;
2375 return parseSSADefOrUseAndType(
2376 [&](UnresolvedOperand useInfo,
Type type) -> ParseResult {
2381 if (definingExistingArgs) {
2384 return emitError(
"too many arguments specified in argument list");
2389 return emitError(
"argument and block argument type mismatch");
2391 auto loc = getEncodedSourceLocation(useInfo.location);
2397 if (parseTrailingLocationSpecifier(arg))
2403 state.asmState->addDefinition(arg, useInfo.location);
2405 return addDefinition(useInfo, arg);
2414 ParseResult OperationParser::codeCompleteSSAUse() {
2415 std::string detailData;
2416 llvm::raw_string_ostream detailOS(detailData);
2417 for (IsolatedSSANameScope &scope : isolatedNameScopes) {
2418 for (
auto &it : scope.values) {
2419 if (it.second.empty())
2421 Value frontValue = it.second.front().value;
2425 if (
auto result = dyn_cast<OpResult>(frontValue)) {
2426 if (!forwardRefPlaceholders.count(result))
2427 detailOS << result.getOwner()->getName() <<
": ";
2429 detailOS <<
"arg #" << cast<BlockArgument>(frontValue).getArgNumber()
2434 detailOS << frontValue.
getType();
2439 if (it.second.size() > 1)
2440 detailOS <<
", ...";
2442 state.codeCompleteContext->appendSSAValueCompletion(
2443 it.getKey(), std::move(detailOS.str()));
2450 ParseResult OperationParser::codeCompleteBlock() {
2453 StringRef spelling = getTokenSpelling();
2454 if (!(spelling.empty() || spelling ==
"^"))
2457 for (
const auto &it : blocksByName.back())
2458 state.codeCompleteContext->appendBlockCompletion(it.getFirst());
2469 class TopLevelOperationParser :
public Parser {
2481 ParseResult parseAttributeAliasDef();
2487 ParseResult parseTypeAliasDef();
2493 ParseResult parseFileMetadataDictionary();
2496 ParseResult parseResourceFileMetadata(
2497 function_ref<ParseResult(StringRef, SMLoc)> parseBody);
2498 ParseResult parseDialectResourceFileMetadata();
2499 ParseResult parseExternalResourceFileMetadata();
2506 ParsedResourceEntry(StringRef key, SMLoc keyLoc,
Token value,
Parser &p)
2507 : key(key), keyLoc(keyLoc), value(value), p(p) {}
2508 ~ParsedResourceEntry()
override =
default;
2510 StringRef getKey() const final {
return key; }
2515 if (value.isAny(Token::kw_true, Token::kw_false))
2517 return value.getSpelling().starts_with(
"\"0x")
2522 FailureOr<bool> parseAsBool() const final {
2523 if (value.is(Token::kw_true))
2525 if (value.is(Token::kw_false))
2527 return p.emitError(value.getLoc(),
2528 "expected 'true' or 'false' value for key '" + key +
2532 FailureOr<std::string> parseAsString() const final {
2533 if (value.isNot(Token::string))
2534 return p.emitError(value.getLoc(),
2535 "expected string value for key '" + key +
"'");
2536 return value.getStringValue();
2539 FailureOr<AsmResourceBlob>
2540 parseAsBlob(BlobAllocatorFn allocator)
const final {
2544 std::optional<std::string> blobData =
2545 value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
2547 return p.emitError(value.getLoc(),
2548 "expected hex string blob for key '" + key +
"'");
2552 if (blobData->size() <
sizeof(uint32_t)) {
2553 return p.emitError(value.getLoc(),
2554 "expected hex string blob for key '" + key +
2555 "' to encode alignment in first 4 bytes");
2557 llvm::support::ulittle32_t align;
2558 memcpy(&align, blobData->data(),
sizeof(uint32_t));
2559 if (align && !llvm::isPowerOf2_32(align)) {
2560 return p.emitError(value.getLoc(),
2561 "expected hex string blob for key '" + key +
2562 "' to encode alignment in first 4 bytes, but got "
2563 "non-power-of-2 value: " +
2568 StringRef data = StringRef(*blobData).drop_front(
sizeof(uint32_t));
2575 assert(llvm::isAddrAligned(llvm::Align(align), blob.
getData().data()) &&
2577 "blob allocator did not return a properly aligned address");
2590 ParseResult TopLevelOperationParser::parseAttributeAliasDef() {
2591 assert(getToken().is(Token::hash_identifier));
2592 StringRef aliasName = getTokenSpelling().drop_front();
2595 if (state.symbols.attributeAliasDefinitions.count(aliasName) > 0)
2596 return emitError(
"redefinition of attribute alias id '" + aliasName +
"'");
2599 if (aliasName.contains(
'.'))
2600 return emitError(
"attribute names with a '.' are reserved for "
2601 "dialect-defined names");
2603 SMRange location = getToken().getLocRange();
2604 consumeToken(Token::hash_identifier);
2607 if (parseToken(Token::equal,
"expected '=' in attribute alias definition"))
2617 state.asmState->addAttrAliasDefinition(aliasName, location, attr);
2618 state.symbols.attributeAliasDefinitions[aliasName] = attr;
2622 ParseResult TopLevelOperationParser::parseTypeAliasDef() {
2623 assert(getToken().is(Token::exclamation_identifier));
2624 StringRef aliasName = getTokenSpelling().drop_front();
2627 if (state.symbols.typeAliasDefinitions.count(aliasName) > 0)
2628 return emitError(
"redefinition of type alias id '" + aliasName +
"'");
2631 if (aliasName.contains(
'.'))
2632 return emitError(
"type names with a '.' are reserved for "
2633 "dialect-defined names");
2635 SMRange location = getToken().getLocRange();
2636 consumeToken(Token::exclamation_identifier);
2639 if (parseToken(Token::equal,
"expected '=' in type alias definition"))
2649 state.asmState->addTypeAliasDefinition(aliasName, location, aliasedType);
2650 state.symbols.typeAliasDefinitions.try_emplace(aliasName, aliasedType);
2654 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() {
2655 consumeToken(Token::file_metadata_begin);
2656 return parseCommaSeparatedListUntil(
2657 Token::file_metadata_end, [&]() -> ParseResult {
2659 SMLoc keyLoc = getToken().getLoc();
2661 if (failed(parseOptionalKeyword(&key)))
2662 return emitError(
"expected identifier key in file "
2663 "metadata dictionary");
2664 if (parseToken(Token::colon,
"expected ':'"))
2668 if (key ==
"dialect_resources")
2669 return parseDialectResourceFileMetadata();
2670 if (key ==
"external_resources")
2671 return parseExternalResourceFileMetadata();
2672 return emitError(keyLoc,
"unknown key '" + key +
2673 "' in file metadata dictionary");
2677 ParseResult TopLevelOperationParser::parseResourceFileMetadata(
2678 function_ref<ParseResult(StringRef, SMLoc)> parseBody) {
2679 if (parseToken(Token::l_brace,
"expected '{'"))
2682 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2684 SMLoc nameLoc = getToken().getLoc();
2686 if (failed(parseOptionalKeyword(&name)))
2687 return emitError(
"expected identifier key for 'resource' entry");
2689 if (parseToken(Token::colon,
"expected ':'") ||
2690 parseToken(Token::l_brace,
"expected '{'"))
2692 return parseBody(name, nameLoc);
2696 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() {
2697 return parseResourceFileMetadata([&](StringRef name,
2698 SMLoc nameLoc) -> ParseResult {
2702 return emitError(nameLoc,
"dialect '" + name +
"' is unknown");
2703 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect);
2705 return emitError() <<
"unexpected 'resource' section for dialect '"
2709 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2711 SMLoc keyLoc = getToken().getLoc();
2713 if (failed(parseResourceHandle(handler, key)) ||
2714 parseToken(Token::colon,
"expected ':'"))
2716 Token valueTok = getToken();
2719 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2720 return handler->parseResource(entry);
2725 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() {
2726 return parseResourceFileMetadata([&](StringRef name,
2727 SMLoc nameLoc) -> ParseResult {
2733 <<
"ignoring unknown external resources for '" << name <<
"'";
2736 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2738 SMLoc keyLoc = getToken().getLoc();
2740 if (failed(parseOptionalKeyword(&key)))
2742 "expected identifier key for 'external_resources' entry");
2743 if (parseToken(Token::colon,
"expected ':'"))
2745 Token valueTok = getToken();
2750 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2760 OperationParser opParser(state, topLevelOp.get());
2762 switch (getToken().getKind()) {
2765 if (opParser.parseOperation())
2771 if (opParser.finalize())
2776 auto &parsedOps = topLevelOp->getBody()->getOperations();
2778 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(),
2790 case Token::hash_identifier:
2791 if (parseAttributeAliasDef())
2796 case Token::exclamation_identifier:
2797 if (parseTypeAliasDef())
2802 case Token::file_metadata_begin:
2803 if (parseFileMetadataDictionary())
2816 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2823 ParserState state(sourceMgr, config, aliasState, asmState,
2824 codeCompleteContext);
2825 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.
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 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 ...
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 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 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-...
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.