39 #include "llvm/ADT/APFloat.h"
40 #include "llvm/ADT/DenseMap.h"
41 #include "llvm/ADT/PointerUnion.h"
42 #include "llvm/ADT/STLExtras.h"
43 #include "llvm/ADT/ScopeExit.h"
44 #include "llvm/ADT/Sequence.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);
313 std::optional<APFloat> &result,
const Token &tok,
bool isNegative,
314 const llvm::fltSemantics &semantics,
size_t typeSizeInBits) {
317 bool isHex = spelling.size() > 1 && spelling[1] ==
'x';
319 return emitError(loc,
"unexpected decimal integer literal for a "
320 "floating point value")
322 <<
"add a trailing dot to make the literal a float";
325 return emitError(loc,
"hexadecimal float literal should not have a "
331 return emitError(loc,
"hexadecimal float constant out of range for type");
333 if (&semantics == &APFloat::IEEEdouble()) {
334 result = APFloat(semantics, APInt(typeSizeInBits, *value));
338 APInt apInt(typeSizeInBits, *value);
340 return emitError(loc,
"hexadecimal float constant out of range for type");
341 result = APFloat(semantics, apInt);
362 assert(dialect &&
"expected valid dialect interface");
365 return emitError(
"expected identifier key for 'resource' entry");
371 std::pair<std::string, AsmDialectResourceHandle> &entry =
372 resources[dialect][name];
373 if (entry.first.empty()) {
377 <<
"unknown 'resource' key '" << name <<
"' for dialect '"
378 << dialect->getDialect()->getNamespace() <<
"'";
381 entry.second = *result;
393 <<
"' does not expect resource handles";
395 StringRef resourceName;
411 if (dialectName.empty() || dialectName.contains(
'.'))
422 auto shouldIgnoreOpCompletion = [&]() {
424 const char *it = loc.getPointer() - 1;
425 for (; it > bufBegin && *it !=
'\n'; --it)
426 if (!StringRef(
" \t\r").contains(*it))
430 if (shouldIgnoreOpCompletion())
448 if (name.consume_back(
"."))
489 class OperationParser :
public Parser {
491 OperationParser(
ParserState &state, ModuleOp topLevelOp);
505 struct DeferredLocInfo {
507 StringRef identifier;
511 void pushSSANameScope(
bool isIsolated);
526 bool allowResultNumber =
true);
530 Value resolveSSAUse(UnresolvedOperand useInfo,
Type type);
539 std::optional<SMLoc> getReferenceLoc(StringRef name,
unsigned number) {
540 auto &values = isolatedNameScopes.back().values;
541 if (!values.count(name) || number >= values[name].size())
543 if (values[name][number].value)
544 return values[name][number].loc;
574 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
577 std::optional<Attribute> propertiesAttribute = std::nullopt,
578 std::optional<FunctionType> parsedFnType = std::nullopt);
595 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument);
604 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>;
622 bool isIsolatedNameScope =
false);
627 bool isIsolatedNameScope);
645 Block *getBlockNamed(StringRef name, SMLoc loc);
660 struct BlockDefinition {
667 struct ValueDefinition {
675 BlockDefinition &getBlockInfoByName(StringRef name) {
676 return blocksByName.back()[name];
680 void insertForwardRef(
Block *block, SMLoc loc) {
681 forwardRef.back().try_emplace(block, loc);
685 bool eraseForwardRef(
Block *block) {
return forwardRef.back().erase(block); }
688 void recordDefinition(StringRef def);
695 Value createForwardRefPlaceholder(SMLoc loc,
Type type);
698 bool isForwardRefPlaceholder(
Value value) {
699 return forwardRefPlaceholders.count(value);
706 struct IsolatedSSANameScope {
708 void recordDefinition(StringRef def) {
709 definitionsPerScope.back().insert(def);
713 void pushSSANameScope() { definitionsPerScope.push_back({}); }
716 void popSSANameScope() {
717 for (
auto &def : definitionsPerScope.pop_back_val())
718 values.erase(def.getKey());
723 llvm::StringMap<SmallVector<ValueDefinition, 1>> values;
745 std::vector<DeferredLocInfo> deferredLocsReferences;
758 OperationParser::OperationParser(
ParserState &state, ModuleOp topLevelOp)
759 :
Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) {
761 pushSSANameScope(
true);
768 OperationParser::~OperationParser() {
769 for (
auto &fwd : forwardRefPlaceholders) {
772 fwd.first.dropAllUses();
773 fwd.first.getDefiningOp()->destroy();
775 for (
const auto &scope : forwardRef) {
776 for (
const auto &fwd : scope) {
779 fwd.first->dropAllUses();
790 if (!forwardRefPlaceholders.empty()) {
793 for (
auto entry : forwardRefPlaceholders)
794 errors.push_back(entry.second.getPointer());
795 llvm::array_pod_sort(errors.begin(), errors.end());
797 for (
const char *entry : errors) {
798 auto loc = SMLoc::getFromPointer(entry);
799 emitError(loc,
"use of undeclared SSA value name");
805 auto &attributeAliases = state.symbols.attributeAliasDefinitions;
806 auto locID = TypeID::get<DeferredLocInfo *>();
807 auto resolveLocation = [&,
this](
auto &opOrArgument) ->
LogicalResult {
808 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc());
809 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID)
811 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()];
812 Attribute attr = attributeAliases.lookup(locInfo.identifier);
815 <<
"operation location alias was never defined";
816 auto locAttr = dyn_cast<LocationAttr>(attr);
819 <<
"expected location, but found '" << attr <<
"'";
820 opOrArgument.setLoc(locAttr);
824 auto walkRes = topLevelOp->walk([&](
Operation *op) {
825 if (
failed(resolveLocation(*op)))
828 for (
Block &block : region.getBlocks())
830 if (
failed(resolveLocation(arg)))
834 if (walkRes.wasInterrupted())
838 if (
failed(popSSANameScope()))
842 if (state.config.shouldVerifyAfterParse() &&
failed(
verify(topLevelOp)))
847 state.asmState->finalize(topLevelOp);
855 void OperationParser::pushSSANameScope(
bool isIsolated) {
861 isolatedNameScopes.push_back({});
862 isolatedNameScopes.back().pushSSANameScope();
866 auto forwardRefInCurrentScope = forwardRef.pop_back_val();
869 if (!forwardRefInCurrentScope.empty()) {
872 for (
auto entry : forwardRefInCurrentScope) {
873 errors.push_back({entry.second.getPointer(), entry.first});
875 topLevelOp->getRegion(0).push_back(entry.first);
877 llvm::array_pod_sort(errors.begin(), errors.end());
879 for (
auto entry : errors) {
880 auto loc = SMLoc::getFromPointer(entry.first);
881 emitError(loc,
"reference to an undefined block");
888 auto ¤tNameScope = isolatedNameScopes.back();
889 if (currentNameScope.definitionsPerScope.size() == 1)
890 isolatedNameScopes.pop_back();
892 currentNameScope.popSSANameScope();
894 blocksByName.pop_back();
899 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo,
901 auto &entries = getSSAValueEntry(useInfo.name);
904 if (entries.size() <= useInfo.number)
905 entries.resize(useInfo.number + 1);
909 if (
auto existing = entries[useInfo.number].value) {
910 if (!isForwardRefPlaceholder(existing)) {
912 .
append(
"redefinition of SSA value '", useInfo.name,
"'")
913 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
914 .
append(
"previously defined here");
917 if (existing.getType() != value.
getType()) {
919 .
append(
"definition of SSA value '", useInfo.name,
"#",
920 useInfo.number,
"' has type ", value.
getType())
921 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
922 .
append(
"previously used here with type ", existing.getType());
928 existing.replaceAllUsesWith(value);
929 existing.getDefiningOp()->destroy();
930 forwardRefPlaceholders.erase(existing);
935 state.asmState->refineDefinition(existing, value);
939 entries[useInfo.number] = {value, useInfo.location};
940 recordDefinition(useInfo.name);
949 ParseResult OperationParser::parseOptionalSSAUseList(
951 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
954 UnresolvedOperand result;
955 if (parseSSAUse(result))
957 results.push_back(result);
966 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result,
967 bool allowResultNumber) {
968 if (getToken().isCodeCompletion())
969 return codeCompleteSSAUse();
971 result.name = getTokenSpelling();
973 result.location = getToken().getLoc();
974 if (parseToken(Token::percent_identifier,
"expected SSA operand"))
978 if (getToken().is(Token::hash_identifier)) {
979 if (!allowResultNumber)
980 return emitError(
"result number not allowed in argument list");
982 if (
auto value = getToken().getHashIdentifierNumber())
983 result.number = *value;
985 return emitError(
"invalid SSA value result number");
986 consumeToken(Token::hash_identifier);
994 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo,
Type type) {
995 auto &entries = getSSAValueEntry(useInfo.name);
999 auto maybeRecordUse = [&](
Value value) {
1001 state.asmState->addUses(value, useInfo.location);
1006 if (useInfo.number < entries.size() && entries[useInfo.number].value) {
1007 Value result = entries[useInfo.number].value;
1010 return maybeRecordUse(result);
1012 emitError(useInfo.location,
"use of value '")
1014 "' expects different type than prior uses: ", type,
" vs ",
1016 .
attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
1017 .
append(
"prior use here");
1022 if (entries.size() <= useInfo.number)
1023 entries.resize(useInfo.number + 1);
1027 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value))
1028 return (
emitError(useInfo.location,
"reference to invalid result number"),
1033 Value result = createForwardRefPlaceholder(useInfo.location, type);
1034 entries[useInfo.number] = {result, useInfo.location};
1035 return maybeRecordUse(result);
1041 ParseResult OperationParser::parseSSADefOrUseAndType(
1043 UnresolvedOperand useInfo;
1044 if (parseSSAUse(useInfo) ||
1045 parseToken(Token::colon,
"expected ':' and type for SSA operand"))
1052 return action(useInfo, type);
1061 ParseResult OperationParser::parseOptionalSSAUseAndTypeList(
1064 if (parseOptionalSSAUseList(valueIDs))
1068 if (valueIDs.empty())
1072 if (parseToken(Token::colon,
"expected ':' in operand list") ||
1073 parseTypeListNoParens(types))
1076 if (valueIDs.size() != types.size())
1078 << valueIDs.size() <<
" types to match operand list";
1080 results.reserve(valueIDs.size());
1081 for (
unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1082 if (
auto value = resolveSSAUse(valueIDs[i], types[i]))
1083 results.push_back(value);
1092 void OperationParser::recordDefinition(StringRef def) {
1093 isolatedNameScopes.back().recordDefinition(def);
1097 auto OperationParser::getSSAValueEntry(StringRef name)
1099 return isolatedNameScopes.back().values[name];
1103 Value OperationParser::createForwardRefPlaceholder(SMLoc loc,
Type type) {
1112 getEncodedSourceLocation(loc), name, type, {},
1113 std::nullopt,
nullptr, {},
1115 forwardRefPlaceholders[op->
getResult(0)] = loc;
1136 auto loc = getToken().getLoc();
1138 size_t numExpectedResults = 0;
1139 if (getToken().is(Token::percent_identifier)) {
1143 Token nameTok = getToken();
1144 if (parseToken(Token::percent_identifier,
1145 "expected valid ssa identifier"))
1149 size_t expectedSubResults = 1;
1150 if (consumeIf(Token::colon)) {
1152 if (!getToken().is(Token::integer))
1153 return emitWrongTokenError(
"expected integer number of results");
1156 auto val = getToken().getUInt64IntegerValue();
1157 if (!val || *val < 1)
1159 "expected named operation to have at least 1 result");
1160 consumeToken(Token::integer);
1161 expectedSubResults = *val;
1164 resultIDs.emplace_back(nameTok.
getSpelling(), expectedSubResults,
1166 numExpectedResults += expectedSubResults;
1172 if (parseToken(Token::equal,
"expected '=' after SSA name"))
1177 Token nameTok = getToken();
1178 if (nameTok.
is(Token::bare_identifier) || nameTok.
isKeyword())
1179 op = parseCustomOperation(resultIDs);
1180 else if (nameTok.
is(Token::string))
1181 op = parseGenericOperation();
1183 return codeCompleteStringDialectOrOperationName(nameTok.
getStringValue());
1185 return codeCompleteDialectOrElidedOpName(loc);
1187 return emitWrongTokenError(
"expected operation name in quotes");
1194 if (!resultIDs.empty()) {
1196 return emitError(loc,
"cannot name an operation with no results");
1198 return emitError(loc,
"operation defines ")
1200 << numExpectedResults <<
" to bind";
1203 if (state.asmState) {
1204 unsigned resultIt = 0;
1206 asmResultGroups.reserve(resultIDs.size());
1207 for (ResultRecord &record : resultIDs) {
1208 asmResultGroups.emplace_back(resultIt, std::get<2>(record));
1209 resultIt += std::get<1>(record);
1211 state.asmState->finalizeOperationDefinition(
1212 op, nameTok.
getLocRange(), getLastToken().getEndLoc(),
1217 unsigned opResI = 0;
1218 for (ResultRecord &resIt : resultIDs) {
1219 for (
unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) {
1220 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes},
1227 }
else if (state.asmState) {
1228 state.asmState->finalizeOperationDefinition(
1230 getLastToken().getEndLoc());
1241 if (getToken().isCodeCompletion())
1242 return codeCompleteBlock();
1245 if (!getToken().is(Token::caret_identifier))
1246 return emitWrongTokenError(
"expected block name");
1247 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1258 if (parseToken(Token::l_square,
"expected '['"))
1261 auto parseElt = [
this, &destinations] {
1264 destinations.push_back(dest);
1267 return parseCommaSeparatedListUntil(Token::r_square, parseElt,
1276 struct CleanupOpStateRegions {
1277 ~CleanupOpStateRegions() {
1279 regionsToClean.reserve(state.regions.size());
1280 for (
auto ®ion : state.regions)
1282 for (
auto &block : *region)
1289 ParseResult OperationParser::parseGenericOperationAfterOpName(
1293 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1295 std::optional<Attribute> propertiesAttribute,
1296 std::optional<FunctionType> parsedFnType) {
1300 if (!parsedOperandUseInfo) {
1301 if (parseToken(Token::l_paren,
"expected '(' to start operand list") ||
1302 parseOptionalSSAUseList(opInfo) ||
1303 parseToken(Token::r_paren,
"expected ')' to end operand list")) {
1306 parsedOperandUseInfo = opInfo;
1310 if (!parsedSuccessors) {
1311 if (getToken().is(Token::l_square)) {
1314 return emitError(
"successors in non-terminator");
1317 if (parseSuccessors(successors))
1326 if (propertiesAttribute) {
1328 }
else if (consumeIf(Token::less)) {
1332 if (parseToken(Token::greater,
"expected '>' to close properties"))
1336 if (!parsedRegions) {
1337 if (consumeIf(Token::l_paren)) {
1341 if (parseRegion(*result.
regions.back(), {}))
1343 }
while (consumeIf(Token::comma));
1344 if (parseToken(Token::r_paren,
"expected ')' to end region list"))
1352 if (!parsedAttributes) {
1353 if (getToken().is(Token::l_brace)) {
1363 if (!parsedFnType) {
1364 if (parseToken(Token::colon,
"expected ':' followed by operation type"))
1367 typeLoc = getEncodedSourceLocation(getToken().getLoc());
1371 auto fnType = dyn_cast<FunctionType>(type);
1375 parsedFnType = fnType;
1378 result.
addTypes(parsedFnType->getResults());
1382 if (operandTypes.size() != parsedOperandUseInfo->size()) {
1383 auto plural =
"s"[parsedOperandUseInfo->size() == 1];
1385 << parsedOperandUseInfo->size() <<
" operand type" << plural
1386 <<
" but had " << operandTypes.size();
1390 for (
unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) {
1392 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i]));
1400 Operation *OperationParser::parseGenericOperation() {
1402 auto srcLocation = getEncodedSourceLocation(getToken().getLoc());
1404 std::string name = getToken().getStringValue();
1406 return (
emitError(
"empty operation name is invalid"),
nullptr);
1407 if (name.find(
'\0') != StringRef::npos)
1408 return (
emitError(
"null character not allowed in operation name"),
nullptr);
1410 consumeToken(Token::string);
1413 CleanupOpStateRegions guard{result};
1417 StringRef dialectName = StringRef(name).split(
'.').first;
1418 if (!
getContext()->getLoadedDialect(dialectName) &&
1419 !
getContext()->getOrLoadDialect(dialectName)) {
1420 if (!
getContext()->allowsUnregisteredDialects()) {
1423 emitError(
"operation being parsed with an unregistered dialect. If "
1424 "this is intended, please use -allow-unregistered-dialect "
1425 "with the MLIR tool used");
1436 state.asmState->startOperationDefinition(result.
name);
1438 if (parseGenericOperationAfterOpName(result))
1462 std::optional<RegisteredOperationName> info =
1466 return mlir::emitError(srcLocation) <<
"'" << name <<
"' op ";
1474 if (parseTrailingLocationSpecifier(op))
1482 << properties <<
" for op " << name <<
": ";
1491 Operation *OperationParser::parseGenericOperation(
Block *insertBlock,
1493 Token nameToken = getToken();
1496 opBuilder.setInsertionPoint(insertBlock, insertPt);
1497 Operation *op = parseGenericOperation();
1504 state.asmState->finalizeOperationDefinition(
1506 getLastToken().getEndLoc());
1511 class CustomOpAsmParser :
public AsmParserImpl<OpAsmParser> {
1516 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser)
1518 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove),
1519 opName(opName), parser(parser) {
1520 (void)isIsolatedFromAbove;
1526 if (parseAssembly(*
this, opState))
1532 std::optional<NamedAttribute> duplicate =
1535 return emitError(getNameLoc(),
"attribute '")
1536 << duplicate->getName().getValue()
1537 <<
"' occurs more than once in the attribute list";
1543 return parser.parseGenericOperation(insertBlock, insertPt);
1547 return parser.parseCustomOperationName();
1554 std::optional<
MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1556 std::optional<Attribute> parsedPropertiesAttribute,
1557 std::optional<FunctionType> parsedFnType)
final {
1558 return parser.parseGenericOperationAfterOpName(
1559 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
1560 parsedAttributes, parsedPropertiesAttribute, parsedFnType);
1575 std::pair<StringRef, unsigned>
1576 getResultName(
unsigned resultNo)
const override {
1578 for (
const auto &entry : resultIDs) {
1579 if (resultNo < std::get<1>(entry)) {
1581 StringRef name = std::get<0>(entry).drop_front();
1582 return {name, resultNo};
1584 resultNo -= std::get<1>(entry);
1593 size_t getNumResults()
const override {
1595 for (
auto &entry : resultIDs)
1596 count += std::get<1>(entry);
1611 ParseResult parseOperand(UnresolvedOperand &result,
1612 bool allowResultNumber =
true)
override {
1614 if (parser.parseSSAUse(useInfo, allowResultNumber))
1623 parseOptionalOperand(UnresolvedOperand &result,
1624 bool allowResultNumber =
true)
override {
1625 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1626 return parseOperand(result, allowResultNumber);
1627 return std::nullopt;
1634 bool allowResultNumber =
true,
1635 int requiredOperandCount = -1)
override {
1640 Token tok = parser.getToken();
1644 if (requiredOperandCount == -1 || requiredOperandCount == 0)
1648 if (tok.
isAny(Token::l_paren, Token::l_square))
1649 return parser.emitError(
"unexpected delimiter");
1650 return parser.emitWrongTokenError(
"expected operand");
1655 return parseOperand(result.emplace_back(), allowResultNumber);
1658 auto startLoc = parser.getToken().getLoc();
1663 if (requiredOperandCount != -1 &&
1664 result.size() !=
static_cast<size_t>(requiredOperandCount))
1666 << requiredOperandCount <<
" operands";
1671 ParseResult resolveOperand(
const UnresolvedOperand &operand,
Type type,
1673 if (
auto value = parser.resolveSSAUse(operand, type)) {
1674 result.push_back(value);
1688 auto parseElement = [&](
bool isSymbol) ->
ParseResult {
1689 UnresolvedOperand operand;
1690 if (parseOperand(operand))
1693 symOperands.push_back(operand);
1695 dimOperands.push_back(operand);
1700 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter))
1705 attrs.
push_back(parser.builder.getNamedAttr(attrName, mapAttr));
1709 operands.assign(dimOperands.begin(), dimOperands.end());
1710 operands.append(symOperands.begin(), symOperands.end());
1719 auto parseElement = [&](
bool isSymbol) ->
ParseResult {
1720 UnresolvedOperand operand;
1721 if (parseOperand(operand))
1724 symbOperands.push_back(operand);
1726 dimOperands.push_back(operand);
1730 return parser.parseAffineExprOfSSAIds(expr, parseElement);
1743 ParseResult parseArgument(Argument &result,
bool allowType =
false,
1744 bool allowAttrs =
false)
override {
1746 if (parseOperand(result.ssaName,
false) ||
1747 (allowType && parseColonType(result.type)) ||
1748 (allowAttrs && parseOptionalAttrDict(attrs)) ||
1749 parseOptionalLocationSpecifier(result.sourceLoc))
1757 bool allowAttrs)
override {
1758 if (parser.getToken().is(Token::percent_identifier))
1759 return parseArgument(result, allowType, allowAttrs);
1760 return std::nullopt;
1764 Delimiter delimiter,
bool allowType,
1765 bool allowAttrs)
override {
1768 parser.getToken().isNot(Token::percent_identifier))
1772 return parseArgument(result.emplace_back(), allowType, allowAttrs);
1775 " in argument list");
1785 bool enableNameShadowing)
override {
1787 (void)isIsolatedFromAbove;
1788 assert((!enableNameShadowing || isIsolatedFromAbove) &&
1789 "name shadowing is only allowed on isolated regions");
1790 if (parser.parseRegion(region, arguments, enableNameShadowing))
1798 bool enableNameShadowing)
override {
1799 if (parser.getToken().isNot(Token::l_brace))
1800 return std::nullopt;
1801 return parseRegion(region, arguments, enableNameShadowing);
1808 parseOptionalRegion(std::unique_ptr<Region> ®ion,
1810 bool enableNameShadowing =
false)
override {
1811 if (parser.getToken().isNot(Token::l_brace))
1812 return std::nullopt;
1813 std::unique_ptr<Region> newRegion = std::make_unique<Region>();
1814 if (parseRegion(*newRegion, arguments, enableNameShadowing))
1817 region = std::move(newRegion);
1827 return parser.parseSuccessor(dest);
1832 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier))
1833 return std::nullopt;
1834 return parseSuccessor(dest);
1839 parseSuccessorAndUseList(
Block *&dest,
1841 if (parseSuccessor(dest))
1846 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) {
1861 if (
failed(parseOptionalLParen()))
1862 return std::nullopt;
1865 if (parseArgument(lhs.emplace_back()) || parseEqual() ||
1866 parseOperand(rhs.emplace_back()))
1870 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt);
1875 parseOptionalLocationSpecifier(std::optional<Location> &result)
override {
1877 if (!parser.consumeIf(Token::kw_loc))
1880 if (parser.parseToken(Token::l_paren,
"expected '(' in location"))
1883 Token tok = parser.getToken();
1887 if (tok.
is(Token::hash_identifier)) {
1888 if (parser.parseLocationAlias(directLoc))
1890 }
else if (parser.parseLocationInstance(directLoc)) {
1894 if (parser.parseToken(Token::r_paren,
"expected ')' in location"))
1907 bool isIsolatedFromAbove;
1911 OperationParser &parser;
1916 Token nameTok = getToken();
1923 std::optional<RegisteredOperationName> opInfo =
1930 auto opNameSplit = opName.split(
'.');
1931 StringRef dialectName = opNameSplit.first;
1932 std::string opNameStorage;
1933 if (opNameSplit.second.empty()) {
1935 if (getToken().isCodeCompletion() && opName.back() ==
'.')
1936 return codeCompleteOperationName(dialectName);
1938 dialectName = getState().defaultDialectStack.back();
1939 opNameStorage = (dialectName +
"." + opName).str();
1940 opName = opNameStorage;
1951 SMLoc opLoc = getToken().
getLoc();
1952 StringRef originalOpName = getTokenSpelling();
1957 StringRef opName = opNameInfo->getStringRef();
1963 bool isIsolatedFromAbove =
false;
1965 StringRef defaultDialect =
"";
1966 if (
auto opInfo = opNameInfo->getRegisteredInfo()) {
1967 parseAssemblyFn = opInfo->getParseAssemblyFn();
1969 auto *iface = opInfo->getInterface<OpAsmOpInterface>();
1970 if (iface && !iface->getDefaultDialect().empty())
1971 defaultDialect = iface->getDefaultDialect();
1973 std::optional<Dialect::ParseOpHook> dialectHook;
1974 Dialect *dialect = opNameInfo->getDialect();
1977 emitError(opLoc) <<
"Dialect `" << opNameInfo->getDialectNamespace()
1978 <<
"' not found for custom op '" << originalOpName
1980 if (originalOpName != opName)
1981 diag <<
" (tried '" << opName <<
"' as well)";
1982 auto ¬e =
diag.attachNote();
1983 note <<
"Registered dialects: ";
1984 llvm::interleaveComma(
getContext()->getAvailableDialects(), note,
1985 [&](StringRef dialect) { note << dialect; });
1986 note <<
" ; for more info on dialect registration see "
1987 "https://mlir.llvm.org/getting_started/Faq/"
1988 "#registered-loaded-dependent-whats-up-with-dialects-management";
1994 emitError(opLoc) <<
"custom op '" << originalOpName <<
"' is unknown";
1995 if (originalOpName != opName)
1996 diag <<
" (tried '" << opName <<
"' as well)";
1999 parseAssemblyFn = *dialectHook;
2001 getState().defaultDialectStack.push_back(defaultDialect);
2002 auto restoreDefaultDialect = llvm::make_scope_exit(
2003 [&]() { getState().defaultDialectStack.pop_back(); });
2007 llvm::PrettyStackTraceFormat fmt(
"MLIR Parser: custom op parser '%s'",
2008 opNameInfo->getIdentifier().data());
2011 auto srcLocation = getEncodedSourceLocation(opLoc);
2016 state.asmState->startOperationDefinition(opState.
name);
2019 CleanupOpStateRegions guard{opState};
2020 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn,
2021 isIsolatedFromAbove, opName, *
this);
2022 if (opAsmParser.parseOperation(opState))
2026 if (opAsmParser.didEmitError())
2034 if (parseTrailingLocationSpecifier(op))
2051 Token tok = getToken();
2052 consumeToken(Token::hash_identifier);
2053 StringRef identifier = tok.
getSpelling().drop_front();
2054 if (identifier.contains(
'.')) {
2056 <<
"expected location, but found dialect attribute: '#" << identifier
2060 state.asmState->addAttrAliasUses(identifier, tok.
getLocRange());
2063 Attribute attr = state.symbols.attributeAliasDefinitions.lookup(identifier);
2065 if (!(loc = dyn_cast<LocationAttr>(attr)))
2067 <<
"expected location, but found '" << attr <<
"'";
2072 TypeID::get<DeferredLocInfo *>(),
2074 deferredLocsReferences.push_back(DeferredLocInfo{tok.
getLoc(), identifier});
2080 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) {
2082 if (!consumeIf(Token::kw_loc))
2084 if (parseToken(Token::l_paren,
"expected '(' in location"))
2086 Token tok = getToken();
2091 if (tok.
is(Token::hash_identifier)) {
2092 if (parseLocationAlias(directLoc))
2094 }
else if (parseLocationInstance(directLoc)) {
2098 if (parseToken(Token::r_paren,
"expected ')' in location"))
2101 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(opOrArgument))
2114 bool isIsolatedNameScope) {
2116 Token lBraceTok = getToken();
2117 if (parseToken(Token::l_brace,
"expected '{' to begin a region"))
2122 state.asmState->startRegionDefinition();
2125 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) &&
2126 parseRegionBody(region, lBraceTok.
getLoc(), entryArguments,
2127 isIsolatedNameScope)) {
2130 consumeToken(Token::r_brace);
2134 state.asmState->finalizeRegionDefinition();
2141 bool isIsolatedNameScope) {
2142 auto currentPt = opBuilder.saveInsertionPoint();
2145 pushSSANameScope(isIsolatedNameScope);
2148 auto owningBlock = std::make_unique<Block>();
2149 Block *block = owningBlock.get();
2154 if (state.asmState && getToken().isNot(Token::caret_identifier))
2155 state.asmState->addDefinition(block, startLoc);
2158 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) {
2160 if (getToken().is(Token::caret_identifier))
2161 return emitError(
"invalid block name in region with named arguments");
2163 for (
auto &entryArg : entryArguments) {
2164 auto &argInfo = entryArg.ssaName;
2167 if (
auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) {
2168 return emitError(argInfo.location,
"region entry argument '" +
2170 "' is already in use")
2171 .
attachNote(getEncodedSourceLocation(*defLoc))
2172 <<
"previously referenced here";
2174 Location loc = entryArg.sourceLoc.has_value()
2175 ? *entryArg.sourceLoc
2176 : getEncodedSourceLocation(argInfo.location);
2181 state.asmState->addDefinition(arg, argInfo.location);
2184 if (addDefinition(argInfo, arg))
2189 if (parseBlock(block))
2193 if (!entryArguments.empty() &&
2195 return emitError(
"entry block arguments were already defined");
2199 region.
push_back(owningBlock.release());
2200 while (getToken().isNot(Token::r_brace)) {
2201 Block *newBlock =
nullptr;
2202 if (parseBlock(newBlock))
2208 if (popSSANameScope())
2212 opBuilder.restoreInsertionPoint(currentPt);
2230 if (block && getToken().isNot(Token::caret_identifier))
2231 return parseBlockBody(block);
2233 SMLoc nameLoc = getToken().getLoc();
2234 auto name = getTokenSpelling();
2235 if (parseToken(Token::caret_identifier,
"expected block name"))
2239 auto &blockAndLoc = getBlockInfoByName(name);
2240 blockAndLoc.loc = nameLoc;
2245 std::unique_ptr<Block> inflightBlock;
2246 auto cleanupOnFailure = llvm::make_scope_exit([&] {
2248 inflightBlock->dropAllDefinedValueUses();
2253 if (!blockAndLoc.block) {
2255 blockAndLoc.block = block;
2257 inflightBlock = std::make_unique<Block>();
2258 blockAndLoc.block = inflightBlock.get();
2265 }
else if (!eraseForwardRef(blockAndLoc.block)) {
2266 return emitError(nameLoc,
"redefinition of block '") << name <<
"'";
2270 inflightBlock.reset(blockAndLoc.block);
2275 state.asmState->addDefinition(blockAndLoc.block, nameLoc);
2276 block = blockAndLoc.block;
2279 if (getToken().is(Token::l_paren))
2280 if (parseOptionalBlockArgList(block))
2282 if (parseToken(Token::colon,
"expected ':' after block name"))
2291 (void)inflightBlock.release();
2297 opBuilder.setInsertionPointToEnd(block);
2300 while (getToken().isNot(Token::caret_identifier, Token::r_brace))
2301 if (parseOperation())
2310 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) {
2311 BlockDefinition &blockDef = getBlockInfoByName(name);
2312 if (!blockDef.block) {
2313 blockDef = {
new Block(), loc};
2314 insertForwardRef(blockDef.block, blockDef.loc);
2319 state.asmState->addUses(blockDef.block, loc);
2321 return blockDef.block;
2331 if (getToken().is(Token::r_brace))
2337 unsigned nextArgument = 0;
2340 return parseSSADefOrUseAndType(
2346 if (definingExistingArgs) {
2349 return emitError(
"too many arguments specified in argument list");
2354 return emitError(
"argument and block argument type mismatch");
2356 auto loc = getEncodedSourceLocation(useInfo.location);
2362 if (parseTrailingLocationSpecifier(arg))
2368 state.asmState->addDefinition(arg, useInfo.location);
2370 return addDefinition(useInfo, arg);
2379 ParseResult OperationParser::codeCompleteSSAUse() {
2380 std::string detailData;
2381 llvm::raw_string_ostream detailOS(detailData);
2382 for (IsolatedSSANameScope &scope : isolatedNameScopes) {
2383 for (
auto &it : scope.values) {
2384 if (it.second.empty())
2386 Value frontValue = it.second.front().value;
2390 if (
auto result = dyn_cast<OpResult>(frontValue)) {
2391 if (!forwardRefPlaceholders.count(result))
2392 detailOS << result.getOwner()->getName() <<
": ";
2394 detailOS <<
"arg #" << cast<BlockArgument>(frontValue).getArgNumber()
2399 detailOS << frontValue.
getType();
2404 if (it.second.size() > 1)
2405 detailOS <<
", ...";
2407 state.codeCompleteContext->appendSSAValueCompletion(
2408 it.getKey(), std::move(detailOS.str()));
2415 ParseResult OperationParser::codeCompleteBlock() {
2418 StringRef spelling = getTokenSpelling();
2419 if (!(spelling.empty() || spelling ==
"^"))
2422 for (
const auto &it : blocksByName.back())
2423 state.codeCompleteContext->appendBlockCompletion(it.getFirst());
2434 class TopLevelOperationParser :
public Parser {
2471 ParsedResourceEntry(StringRef key, SMLoc keyLoc,
Token value,
Parser &p)
2472 : key(key), keyLoc(keyLoc), value(value), p(p) {}
2473 ~ParsedResourceEntry()
override =
default;
2475 StringRef getKey() const final {
return key; }
2480 if (value.isAny(Token::kw_true, Token::kw_false))
2482 return value.getSpelling().starts_with(
"\"0x")
2488 if (value.is(Token::kw_true))
2490 if (value.is(Token::kw_false))
2492 return p.emitError(value.getLoc(),
2493 "expected 'true' or 'false' value for key '" + key +
2498 if (value.isNot(Token::string))
2499 return p.emitError(value.getLoc(),
2500 "expected string value for key '" + key +
"'");
2501 return value.getStringValue();
2505 parseAsBlob(BlobAllocatorFn allocator)
const final {
2509 std::optional<std::string> blobData =
2510 value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
2512 return p.emitError(value.getLoc(),
2513 "expected hex string blob for key '" + key +
"'");
2517 if (blobData->size() <
sizeof(uint32_t)) {
2518 return p.emitError(value.getLoc(),
2519 "expected hex string blob for key '" + key +
2520 "' to encode alignment in first 4 bytes");
2522 llvm::support::ulittle32_t align;
2523 memcpy(&align, blobData->data(),
sizeof(uint32_t));
2524 if (align && !llvm::isPowerOf2_32(align)) {
2525 return p.emitError(value.getLoc(),
2526 "expected hex string blob for key '" + key +
2527 "' to encode alignment in first 4 bytes, but got "
2528 "non-power-of-2 value: " +
2533 StringRef data = StringRef(*blobData).drop_front(
sizeof(uint32_t));
2540 assert(llvm::isAddrAligned(llvm::Align(align), blob.
getData().data()) &&
2542 "blob allocator did not return a properly aligned address");
2555 ParseResult TopLevelOperationParser::parseAttributeAliasDef() {
2556 assert(getToken().is(Token::hash_identifier));
2557 StringRef aliasName = getTokenSpelling().drop_front();
2560 if (state.symbols.attributeAliasDefinitions.count(aliasName) > 0)
2561 return emitError(
"redefinition of attribute alias id '" + aliasName +
"'");
2564 if (aliasName.contains(
'.'))
2565 return emitError(
"attribute names with a '.' are reserved for "
2566 "dialect-defined names");
2568 SMRange location = getToken().getLocRange();
2569 consumeToken(Token::hash_identifier);
2572 if (parseToken(Token::equal,
"expected '=' in attribute alias definition"))
2582 state.asmState->addAttrAliasDefinition(aliasName, location, attr);
2583 state.symbols.attributeAliasDefinitions[aliasName] = attr;
2587 ParseResult TopLevelOperationParser::parseTypeAliasDef() {
2588 assert(getToken().is(Token::exclamation_identifier));
2589 StringRef aliasName = getTokenSpelling().drop_front();
2592 if (state.symbols.typeAliasDefinitions.count(aliasName) > 0)
2593 return emitError(
"redefinition of type alias id '" + aliasName +
"'");
2596 if (aliasName.contains(
'.'))
2597 return emitError(
"type names with a '.' are reserved for "
2598 "dialect-defined names");
2600 SMRange location = getToken().getLocRange();
2601 consumeToken(Token::exclamation_identifier);
2604 if (parseToken(Token::equal,
"expected '=' in type alias definition"))
2614 state.asmState->addTypeAliasDefinition(aliasName, location, aliasedType);
2615 state.symbols.typeAliasDefinitions.try_emplace(aliasName, aliasedType);
2619 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() {
2620 consumeToken(Token::file_metadata_begin);
2621 return parseCommaSeparatedListUntil(
2624 SMLoc keyLoc = getToken().getLoc();
2626 if (
failed(parseOptionalKeyword(&key)))
2627 return emitError(
"expected identifier key in file "
2628 "metadata dictionary");
2629 if (parseToken(Token::colon,
"expected ':'"))
2633 if (key ==
"dialect_resources")
2634 return parseDialectResourceFileMetadata();
2635 if (key ==
"external_resources")
2636 return parseExternalResourceFileMetadata();
2637 return emitError(keyLoc,
"unknown key '" + key +
2638 "' in file metadata dictionary");
2642 ParseResult TopLevelOperationParser::parseResourceFileMetadata(
2644 if (parseToken(Token::l_brace,
"expected '{'"))
2647 return parseCommaSeparatedListUntil(Token::r_brace, [&]() ->
ParseResult {
2649 SMLoc nameLoc = getToken().getLoc();
2651 if (
failed(parseOptionalKeyword(&name)))
2652 return emitError(
"expected identifier key for 'resource' entry");
2654 if (parseToken(Token::colon,
"expected ':'") ||
2655 parseToken(Token::l_brace,
"expected '{'"))
2657 return parseBody(name, nameLoc);
2661 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() {
2662 return parseResourceFileMetadata([&](StringRef name,
2667 return emitError(nameLoc,
"dialect '" + name +
"' is unknown");
2668 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect);
2670 return emitError() <<
"unexpected 'resource' section for dialect '"
2674 return parseCommaSeparatedListUntil(Token::r_brace, [&]() ->
ParseResult {
2676 SMLoc keyLoc = getToken().getLoc();
2678 if (
failed(parseResourceHandle(handler, key)) ||
2679 parseToken(Token::colon,
"expected ':'"))
2681 Token valueTok = getToken();
2684 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2685 return handler->parseResource(entry);
2690 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() {
2691 return parseResourceFileMetadata([&](StringRef name,
2698 <<
"ignoring unknown external resources for '" << name <<
"'";
2701 return parseCommaSeparatedListUntil(Token::r_brace, [&]() ->
ParseResult {
2703 SMLoc keyLoc = getToken().getLoc();
2705 if (
failed(parseOptionalKeyword(&key)))
2707 "expected identifier key for 'external_resources' entry");
2708 if (parseToken(Token::colon,
"expected ':'"))
2710 Token valueTok = getToken();
2715 ParsedResourceEntry entry(key, keyLoc, valueTok, *
this);
2725 OperationParser opParser(state, topLevelOp.get());
2727 switch (getToken().getKind()) {
2730 if (opParser.parseOperation())
2736 if (opParser.finalize())
2741 auto &parsedOps = topLevelOp->getBody()->getOperations();
2743 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(),
2755 case Token::hash_identifier:
2756 if (parseAttributeAliasDef())
2761 case Token::exclamation_identifier:
2762 if (parseTypeAliasDef())
2767 case Token::file_metadata_begin:
2768 if (parseFileMetadataDictionary())
2781 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2788 ParserState state(sourceMgr, config, aliasState, asmState,
2789 codeCompleteContext);
2790 return TopLevelOperationParser(state).parse(block, parserLoc);
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 provides support for representing a failure result, or a valid value of type T.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
InFlightDiagnostic & append(Args &&...args) &
Append arguments to the diagnostic.
const char * getBufferBegin()
Returns the start of the buffer.
Location objects represent source locations information in MLIR.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
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 success/failure for parsing-like operations that find it important to chain tog...
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 ...
static std::optional< uint64_t > getUInt64IntegerValue(StringRef spelling)
For an integer token, return its value as an uint64_t.
bool isAny(Kind k1, Kind k2) const
bool isCodeCompletion() const
Returns true if the current token represents a code completion.
StringRef getSpelling() const
bool isOrIsCodeCompletionFor(Kind kind) const
Returns true if the current token is the given type, or represents a code completion for that type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
static WalkResult advance()
static WalkResult interrupt()
This class provides the implementation of the generic parser methods within AsmParser.
InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override
Emit a diagnostic at the specified location and return failure.
This class implement support for parsing global entities like attributes and types.
ParseResult parseOptionalKeyword(StringRef *keyword)
Parse a keyword, if present, into 'keyword'.
ParseResult parseToken(Token::Kind expectedToken, const Twine &message)
Consume the specified token if present and return success.
ParseResult parseCommaSeparatedListUntil(Token::Kind rightToken, function_ref< ParseResult()> parseElement, bool allowEmptyList=true)
Parse a comma-separated list of elements up until the specified end token.
ParseResult codeCompleteOperationName(StringRef dialectName)
ParserState & getState() const
Location getEncodedSourceLocation(SMLoc loc)
Encode the specified source location information into an attribute for attachment to the IR.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error and return failure.
ParserState & state
The Parser is subclassed and reinstantiated.
ParseResult codeCompleteDialectName()
The set of various code completion methods.
StringRef getTokenSpelling() const
void consumeToken()
Advance the current lexer onto the next token.
ParseResult codeCompleteExpectedTokens(ArrayRef< StringRef > tokens)
Attribute codeCompleteAttribute()
ParseResult codeCompleteDialectOrElidedOpName(SMLoc loc)
InFlightDiagnostic emitWrongTokenError(const Twine &message={})
Emit an error about a "wrong token".
ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())
Parse a list of comma-separated items with an optional delimiter.
OptionalParseResult parseOptionalInteger(APInt &result)
Parse an optional integer value from the stream.
bool isCurrentTokenAKeyword() const
Returns true if the current token corresponds to a keyword.
ParseResult codeCompleteStringDialectOrOperationName(StringRef name)
ParseResult parseFloatFromIntegerLiteral(std::optional< APFloat > &result, const Token &tok, bool isNegative, const llvm::fltSemantics &semantics, size_t typeSizeInBits)
Parse a floating point value from an integer literal token.
ParseResult codeCompleteOptionalTokens(ArrayRef< StringRef > tokens)
const Token & getToken() const
Return the current token the parser is inspecting.
FailureOr< AsmDialectResourceHandle > parseResourceHandle(const OpAsmDialectInterface *dialect, StringRef &name)
Parse a handle to a dialect resource within the assembly format.
bool consumeIf(Token::Kind kind)
If the current token has the specified kind, consume it and return true.
Attribute codeCompleteDialectSymbol(const llvm::StringMap< Attribute > &aliases)
LogicalResult parseCommaSeparatedList(llvm::cl::Option &opt, StringRef argName, StringRef optionStr, function_ref< LogicalResult(StringRef)> elementParseFn)
Parse a string containing a list of comma-delimited elements, invoking the given parser for each sub-...
Detect if any of the given parameter types has a sub-element handler.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
llvm::PointerUnion< NamedAttribute *, NamedProperty *, NamedTypeConstraint * > Argument
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
LogicalResult parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, const ParserConfig &config, AsmParserState *asmState=nullptr, AsmParserCodeCompleteContext *codeCompleteContext=nullptr)
This parses the file specified by the indicated SourceMgr and appends parsed operations to the given ...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Attribute parseAttribute(llvm::StringRef attrStr, MLIRContext *context, Type type={}, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR attribute to an MLIR context if it was valid.
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,...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
void addRegions(MutableArrayRef< std::unique_ptr< Region >> regions)
Take ownership of a set of regions that should be attached to the Operation.
OpaqueProperties getRawProperties()
SmallVector< Value, 4 > operands
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addSuccessors(Block *successor)
void addTypes(ArrayRef< Type > newTypes)
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
This class refers to all of the state maintained globally by the parser, such as the current lexer po...
SymbolState & symbols
The current state for symbol parsing.
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.