25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/ADT/TypeSwitch.h"
27 #include "llvm/Support/FormatVariadic.h"
28 #include "llvm/Support/SaveAndRestore.h"
29 #include "llvm/Support/ScopedPrinter.h"
30 #include "llvm/TableGen/Error.h"
31 #include "llvm/TableGen/Parser.h"
47 : ctx(ctx), lexer(sourceMgr, ctx.
getDiagEngine(), codeCompleteContext),
48 curToken(lexer.lexToken()), enableDocumentation(enableDocumentation),
53 codeCompleteContext(codeCompleteContext) {}
56 FailureOr<ast::Module *> parseModule();
64 enum class ParserContext {
81 enum class OpResultTypeContext {
100 return (curDeclScope = newScope);
102 void pushDeclScope(
ast::DeclScope *scope) { curDeclScope = scope; }
105 void popDeclScope() { curDeclScope = curDeclScope->
getParentScope(); }
114 LogicalResult convertExpressionTo(
121 LogicalResult convertTupleExpressionTo(
132 const ods::Operation *lookupODSOperation(std::optional<StringRef> opName) {
138 StringRef processDoc(StringRef doc) {
139 return enableDocumentation ? doc : StringRef();
144 std::string processAndFormatDoc(
const Twine &doc) {
145 if (!enableDocumentation)
149 llvm::raw_string_ostream docOS(docStr);
150 std::string tmpDocStr = doc.str();
152 StringRef(tmpDocStr).rtrim(
" \t"));
162 LogicalResult parseTdInclude(StringRef filename, SMRange fileLoc,
166 void processTdIncludeRecords(
const llvm::RecordKeeper &tdRecords,
171 template <
typename Constra
intT>
173 createODSNativePDLLConstraintDecl(StringRef name, StringRef codeBlock,
175 StringRef nativeType, StringRef docString);
176 template <
typename Constra
intT>
180 StringRef nativeType);
186 struct ParsedPatternMetadata {
187 std::optional<uint16_t> benefit;
188 bool hasBoundedRecursion =
false;
191 FailureOr<ast::Decl *> parseTopLevelDecl();
192 FailureOr<ast::NamedAttributeDecl *>
193 parseNamedAttributeDecl(std::optional<StringRef> parentOpName);
197 FailureOr<ast::VariableDecl *> parseArgumentDecl();
201 FailureOr<ast::VariableDecl *> parseResultDecl(
unsigned resultNum);
205 FailureOr<ast::UserConstraintDecl *>
206 parseUserConstraintDecl(
bool isInline =
false);
210 FailureOr<ast::UserConstraintDecl *> parseInlineUserConstraintDecl();
214 FailureOr<ast::UserConstraintDecl *> parseUserPDLLConstraintDecl(
221 FailureOr<ast::UserRewriteDecl *> parseUserRewriteDecl(
bool isInline =
false);
225 FailureOr<ast::UserRewriteDecl *> parseInlineUserRewriteDecl();
229 FailureOr<ast::UserRewriteDecl *> parseUserPDLLRewriteDecl(
237 template <
typename T,
typename ParseUserPDLLDeclFnT>
238 FailureOr<T *> parseUserConstraintOrRewriteDecl(
239 ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
240 StringRef anonymousNamePrefix,
bool isInline);
244 template <
typename T>
245 FailureOr<T *> parseUserNativeConstraintOrRewriteDecl(
252 LogicalResult parseUserConstraintOrRewriteSignature(
259 LogicalResult validateUserConstraintOrRewriteReturn(
265 FailureOr<ast::CompoundStmt *>
267 bool expectTerminalSemicolon =
true);
268 FailureOr<ast::CompoundStmt *> parsePatternLambdaBody();
269 FailureOr<ast::Decl *> parsePatternDecl();
270 LogicalResult parsePatternDeclMetadata(ParsedPatternMetadata &metadata);
274 LogicalResult checkDefineNamedDecl(
const ast::Name &name);
278 FailureOr<ast::VariableDecl *>
279 defineVariableDecl(StringRef name, SMRange nameLoc,
ast::Type type,
282 FailureOr<ast::VariableDecl *>
283 defineVariableDecl(StringRef name, SMRange nameLoc,
ast::Type type,
287 LogicalResult parseVariableDeclConstraintList(
291 FailureOr<ast::Expr *> parseTypeConstraintExpr();
299 FailureOr<ast::ConstraintRef>
300 parseConstraint(std::optional<SMRange> &typeConstraint,
302 bool allowInlineTypeConstraints);
307 FailureOr<ast::ConstraintRef> parseArgOrResultConstraint();
312 FailureOr<ast::Expr *> parseExpr();
315 FailureOr<ast::Expr *> parseAttributeExpr();
316 FailureOr<ast::Expr *> parseCallExpr(
ast::Expr *parentExpr,
317 bool isNegated =
false);
318 FailureOr<ast::Expr *> parseDeclRefExpr(StringRef name, SMRange loc);
319 FailureOr<ast::Expr *> parseIdentifierExpr();
320 FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr();
321 FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr();
322 FailureOr<ast::Expr *> parseMemberAccessExpr(
ast::Expr *parentExpr);
323 FailureOr<ast::Expr *> parseNegatedExpr();
324 FailureOr<ast::OpNameDecl *> parseOperationName(
bool allowEmptyName =
false);
325 FailureOr<ast::OpNameDecl *> parseWrappedOperationName(
bool allowEmptyName);
326 FailureOr<ast::Expr *>
327 parseOperationExpr(OpResultTypeContext inputResultTypeContext =
328 OpResultTypeContext::Explicit);
329 FailureOr<ast::Expr *> parseTupleExpr();
330 FailureOr<ast::Expr *> parseTypeExpr();
331 FailureOr<ast::Expr *> parseUnderscoreExpr();
336 FailureOr<ast::Stmt *> parseStmt(
bool expectTerminalSemicolon =
true);
337 FailureOr<ast::CompoundStmt *> parseCompoundStmt();
338 FailureOr<ast::EraseStmt *> parseEraseStmt();
339 FailureOr<ast::LetStmt *> parseLetStmt();
340 FailureOr<ast::ReplaceStmt *> parseReplaceStmt();
341 FailureOr<ast::ReturnStmt *> parseReturnStmt();
342 FailureOr<ast::RewriteStmt *> parseRewriteStmt();
357 FailureOr<ast::PatternDecl *>
358 createPatternDecl(SMRange loc,
const ast::Name *name,
359 const ParsedPatternMetadata &metadata,
368 template <
typename T>
369 FailureOr<T *> createUserPDLLConstraintOrRewriteDecl(
376 FailureOr<ast::VariableDecl *>
377 createVariableDecl(StringRef name, SMRange loc,
ast::Expr *initializer,
382 FailureOr<ast::VariableDecl *>
383 createArgOrResultVariableDecl(StringRef name, SMRange loc,
400 LogicalResult validateTypeConstraintExpr(
const ast::Expr *typeExpr);
401 LogicalResult validateTypeRangeConstraintExpr(
const ast::Expr *typeExpr);
406 FailureOr<ast::CallExpr *>
407 createCallExpr(SMRange loc,
ast::Expr *parentExpr,
409 bool isNegated =
false);
410 FailureOr<ast::DeclRefExpr *> createDeclRefExpr(SMRange loc,
ast::Decl *decl);
411 FailureOr<ast::DeclRefExpr *>
412 createInlineVariableExpr(
ast::Type type, StringRef name, SMRange loc,
414 FailureOr<ast::MemberAccessExpr *>
415 createMemberAccessExpr(
ast::Expr *parentExpr, StringRef name, SMRange loc);
419 FailureOr<ast::Type> validateMemberAccess(
ast::Expr *parentExpr,
420 StringRef name, SMRange loc);
421 FailureOr<ast::OperationExpr *>
423 OpResultTypeContext resultTypeContext,
428 validateOperationOperands(SMRange loc, std::optional<StringRef> name,
431 LogicalResult validateOperationResults(SMRange loc,
432 std::optional<StringRef> name,
435 void checkOperationResultTypeInferrence(SMRange loc, StringRef name,
437 LogicalResult validateOperationOperandsOrResults(
438 StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
442 FailureOr<ast::TupleExpr *> createTupleExpr(SMRange loc,
449 FailureOr<ast::EraseStmt *> createEraseStmt(SMRange loc,
ast::Expr *rootOp);
450 FailureOr<ast::ReplaceStmt *>
451 createReplaceStmt(SMRange loc,
ast::Expr *rootOp,
453 FailureOr<ast::RewriteStmt *>
454 createRewriteStmt(SMRange loc,
ast::Expr *rootOp,
465 LogicalResult codeCompleteMemberAccess(
ast::Expr *parentExpr);
466 LogicalResult codeCompleteAttributeName(std::optional<StringRef> opName);
467 LogicalResult codeCompleteConstraintName(
ast::Type inferredType,
468 bool allowInlineTypeConstraints);
469 LogicalResult codeCompleteDialectName();
470 LogicalResult codeCompleteOperationName(StringRef dialectName);
471 LogicalResult codeCompletePatternMetadata();
472 LogicalResult codeCompleteIncludeFilename(StringRef curPath);
474 void codeCompleteCallSignature(
ast::Node *parent,
unsigned currentNumArgs);
475 void codeCompleteOperationOperandsSignature(std::optional<StringRef> opName,
476 unsigned currentNumOperands);
477 void codeCompleteOperationResultsSignature(std::optional<StringRef> opName,
478 unsigned currentNumResults);
487 if (curToken.isNot(
kind))
494 void consumeToken() {
496 "shouldn't advance past EOF or errors");
497 curToken = lexer.lexToken();
504 assert(curToken.is(
kind) &&
"consumed an unexpected token");
509 void resetToken(SMRange tokLoc) {
510 lexer.resetPointer(tokLoc.Start.getPointer());
511 curToken = lexer.lexToken();
517 if (curToken.getKind() !=
kind)
518 return emitError(curToken.getLoc(), msg);
522 LogicalResult
emitError(SMRange loc,
const Twine &msg) {
523 lexer.emitError(loc, msg);
526 LogicalResult
emitError(
const Twine &msg) {
527 return emitError(curToken.getLoc(), msg);
529 LogicalResult emitErrorAndNote(SMRange loc,
const Twine &msg, SMRange noteLoc,
531 lexer.emitErrorAndNote(loc, msg, noteLoc, note);
550 bool enableDocumentation;
554 llvm::SpecificBumpPtrAllocator<ast::DeclScope> scopeAllocator;
557 ParserContext parserContext = ParserContext::Global;
565 unsigned anonymousDeclNameCounter = 0;
572 FailureOr<ast::Module *> Parser::parseModule() {
573 SMLoc moduleLoc = curToken.getStartLoc();
578 if (
failed(parseModuleBody(decls)))
579 return popDeclScope(), failure();
588 if (
failed(parseDirective(decls)))
593 FailureOr<ast::Decl *> decl = parseTopLevelDecl();
596 decls.push_back(*decl);
606 LogicalResult Parser::convertExpressionTo(
610 if (exprType == type)
615 expr->
getLoc(), llvm::formatv(
"unable to convert expression of type "
616 "`{0}` to the expected type of "
624 if (
auto exprOpType = dyn_cast<ast::OperationType>(exprType))
625 return convertOpExpressionTo(expr, exprOpType, type, emitConvertError);
631 if ((exprType == valueTy || exprType == valueRangeTy) &&
632 (type == valueTy || type == valueRangeTy))
634 if ((exprType == typeTy || exprType == typeRangeTy) &&
635 (type == typeTy || type == typeRangeTy))
639 if (
auto exprTupleType = dyn_cast<ast::TupleType>(exprType))
640 return convertTupleExpressionTo(expr, exprTupleType, type, emitConvertError,
643 return emitConvertError();
646 LogicalResult Parser::convertOpExpressionTo(
651 if (
auto opType = dyn_cast<ast::OperationType>(type)) {
652 if (opType.getName())
653 return emitErrorFn();
658 if (type == valueRangeTy) {
665 if (type == valueTy) {
669 if (odsOp->getResults().empty()) {
670 return emitErrorFn()->attachNote(
671 llvm::formatv(
"see the definition of `{0}`, which was defined "
677 unsigned numSingleResults = llvm::count_if(
679 return result.getVariableLengthKind() ==
680 ods::VariableLengthKind::Single;
682 if (numSingleResults > 1) {
683 return emitErrorFn()->attachNote(
684 llvm::formatv(
"see the definition of `{0}`, which was defined "
685 "with at least {1} results",
686 odsOp->getName(), numSingleResults),
695 return emitErrorFn();
698 LogicalResult Parser::convertTupleExpressionTo(
703 if (
auto tupleType = dyn_cast<ast::TupleType>(type)) {
704 if (tupleType.size() != exprType.
size())
705 return emitErrorFn();
710 for (
unsigned i = 0, e = exprType.
size(); i < e; ++i) {
712 ctx, expr->
getLoc(), expr, llvm::to_string(i),
716 diag.attachNote(llvm::formatv(
"when converting element #{0} of `{1}`",
721 if (
failed(convertExpressionTo(newExprs.back(),
722 tupleType.getElementTypes()[i], diagFn)))
726 tupleType.getElementNames());
734 if (parserContext != ParserContext::Rewrite) {
735 return emitErrorFn()->attachNote(
"Tuple to Range conversion is currently "
736 "only allowed within a rewrite context");
741 if (!llvm::is_contained(allowedElementTypes, elementType))
742 return emitErrorFn();
747 for (
unsigned i = 0, e = exprType.
size(); i < e; ++i) {
749 ctx, expr->
getLoc(), expr, llvm::to_string(i),
755 if (type == valueRangeTy)
756 return convertToRange({valueTy, valueRangeTy}, valueRangeTy);
757 if (type == typeRangeTy)
758 return convertToRange({typeTy, typeRangeTy}, typeRangeTy);
760 return emitErrorFn();
768 StringRef directive = curToken.getSpelling();
769 if (directive ==
"#include")
770 return parseInclude(decls);
772 return emitError(
"unknown directive `" + directive +
"`");
776 SMRange loc = curToken.getLoc();
781 return codeCompleteIncludeFilename(curToken.getStringValue());
784 if (!curToken.isString())
786 "expected string file name after `include` directive");
787 SMRange fileLoc = curToken.getLoc();
788 std::string filenameStr = curToken.getStringValue();
789 StringRef filename = filenameStr;
794 if (filename.ends_with(
".pdll")) {
795 if (
failed(lexer.pushInclude(filename, fileLoc)))
797 "unable to open include file `" + filename +
"`");
802 curToken = lexer.lexToken();
803 LogicalResult result = parseModuleBody(decls);
804 curToken = lexer.lexToken();
809 if (filename.ends_with(
".td"))
810 return parseTdInclude(filename, fileLoc, decls);
813 "expected include filename to end with `.pdll` or `.td`");
816 LogicalResult Parser::parseTdInclude(StringRef filename, llvm::SMRange fileLoc,
818 llvm::SourceMgr &parserSrcMgr = lexer.getSourceMgr();
821 std::string includedFile;
822 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> includeBuffer =
823 parserSrcMgr.OpenIncludeFile(filename.str(), includedFile);
825 return emitError(fileLoc,
"unable to open include file `" + filename +
"`");
828 llvm::SourceMgr tdSrcMgr;
829 tdSrcMgr.AddNewSourceBuffer(std::move(*includeBuffer), SMLoc());
830 tdSrcMgr.setIncludeDirs(parserSrcMgr.getIncludeDirs());
834 struct DiagHandlerContext {
838 } handlerContext{*
this, filename, fileLoc};
841 tdSrcMgr.setDiagHandler(
842 [](
const llvm::SMDiagnostic &
diag,
void *rawHandlerContext) {
843 auto *ctx =
reinterpret_cast<DiagHandlerContext *
>(rawHandlerContext);
844 (void)ctx->parser.emitError(
846 llvm::formatv(
"error while processing include file `{0}`: {1}",
847 ctx->filename,
diag.getMessage()));
852 llvm::RecordKeeper tdRecords;
853 if (llvm::TableGenParseFile(tdSrcMgr, tdRecords))
857 processTdIncludeRecords(tdRecords, decls);
862 parserSrcMgr.takeSourceBuffersFrom(tdSrcMgr, fileLoc.End);
866 void Parser::processTdIncludeRecords(
const llvm::RecordKeeper &tdRecords,
869 auto getLengthKind = [](
const auto &value) {
870 if (value.isOptional())
881 cst.constraint.getUniqueDefName(),
882 processDoc(cst.constraint.getSummary()), cst.constraint.getCppType());
884 auto convertLocToRange = [&](llvm::SMLoc loc) -> llvm::SMRange {
885 return {loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)};
890 for (
const llvm::Record *def : tdRecords.getAllDerivedDefinitions(
"Op")) {
894 bool supportsResultTypeInferrence =
895 op.getTrait(
"::mlir::InferTypeOpInterface::Trait");
898 op.getOperationName(), processDoc(op.getSummary()),
899 processAndFormatDoc(op.getDescription()), op.getQualCppClassName(),
900 supportsResultTypeInferrence, op.getLoc().front());
907 odsOp->appendAttribute(attr.name, attr.attr.isOptional(),
909 attr.attr.getUniqueDefName(),
910 processDoc(attr.attr.getSummary()),
911 attr.attr.getStorageType()));
914 odsOp->appendOperand(operand.name, getLengthKind(operand),
915 addTypeConstraint(operand));
918 odsOp->appendResult(result.name, getLengthKind(result),
919 addTypeConstraint(result));
923 auto shouldBeSkipped = [
this](
const llvm::Record *def) {
924 return def->isAnonymous() || curDeclScope->lookup(def->getName()) ||
925 def->isSubClassOf(
"DeclareInterfaceMethods");
929 for (
const llvm::Record *def : tdRecords.getAllDerivedDefinitions(
"Attr")) {
930 if (shouldBeSkipped(def))
934 decls.push_back(createODSNativePDLLConstraintDecl<ast::AttrConstraintDecl>(
935 constraint, convertLocToRange(def->getLoc().front()), attrTy,
936 constraint.getStorageType()));
939 for (
const llvm::Record *def : tdRecords.getAllDerivedDefinitions(
"Type")) {
940 if (shouldBeSkipped(def))
944 decls.push_back(createODSNativePDLLConstraintDecl<ast::TypeConstraintDecl>(
945 constraint, convertLocToRange(def->getLoc().front()), typeTy,
946 constraint.getCppType()));
950 for (
const llvm::Record *def :
951 tdRecords.getAllDerivedDefinitions(
"OpInterface")) {
952 if (shouldBeSkipped(def))
955 SMRange loc = convertLocToRange(def->getLoc().front());
957 std::string cppClassName =
958 llvm::formatv(
"{0}::{1}", def->getValueAsString(
"cppNamespace"),
959 def->getValueAsString(
"cppInterfaceName"))
961 std::string codeBlock =
962 llvm::formatv(
"return ::mlir::success(llvm::isa<{0}>(self));",
967 processAndFormatDoc(def->getValueAsString(
"description"));
968 decls.push_back(createODSNativePDLLConstraintDecl<ast::OpConstraintDecl>(
969 def->getName(), codeBlock, loc, opTy, cppClassName, desc));
973 template <
typename Constra
intT>
974 ast::Decl *Parser::createODSNativePDLLConstraintDecl(
975 StringRef name, StringRef codeBlock, SMRange loc,
ast::Type type,
976 StringRef nativeType, StringRef docString) {
982 argScope->
add(paramVar);
989 constraintDecl->setDocComment(ctx, docString);
990 curDeclScope->add(constraintDecl);
991 return constraintDecl;
994 template <
typename Constra
intT>
998 StringRef nativeType) {
1009 std::string docString;
1010 if (enableDocumentation) {
1012 docString = processAndFormatDoc(
1017 return createODSNativePDLLConstraintDecl<ConstraintT>(
1026 FailureOr<ast::Decl *> Parser::parseTopLevelDecl() {
1027 FailureOr<ast::Decl *> decl;
1028 switch (curToken.getKind()) {
1030 decl = parseUserConstraintDecl();
1033 decl = parsePatternDecl();
1036 decl = parseUserRewriteDecl();
1039 return emitError(
"expected top-level declaration, such as a `Pattern`");
1046 if (
failed(checkDefineNamedDecl(*name)))
1048 curDeclScope->add(*decl);
1053 FailureOr<ast::NamedAttributeDecl *>
1054 Parser::parseNamedAttributeDecl(std::optional<StringRef> parentOpName) {
1057 return codeCompleteAttributeName(parentOpName);
1059 std::string attrNameStr;
1060 if (curToken.isString())
1061 attrNameStr = curToken.getStringValue();
1063 attrNameStr = curToken.getSpelling().str();
1065 return emitError(
"expected identifier or string attribute name");
1072 FailureOr<ast::Expr *> attrExpr = parseExpr();
1075 attrValue = *attrExpr;
1085 FailureOr<ast::CompoundStmt *> Parser::parseLambdaBody(
1087 bool expectTerminalSemicolon) {
1091 SMLoc bodyStartLoc = curToken.getStartLoc();
1093 FailureOr<ast::Stmt *> singleStatement = parseStmt(expectTerminalSemicolon);
1094 bool failedToParse =
1095 failed(singleStatement) ||
failed(processStatementFn(*singleStatement));
1100 SMRange bodyLoc(bodyStartLoc, curToken.getStartLoc());
1104 FailureOr<ast::VariableDecl *> Parser::parseArgumentDecl() {
1107 return emitError(
"expected identifier argument name");
1110 StringRef name = curToken.getSpelling();
1111 SMRange nameLoc = curToken.getLoc();
1115 parseToken(
Token::colon,
"expected `:` before argument constraint")))
1118 FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1122 return createArgOrResultVariableDecl(name, nameLoc, *cst);
1125 FailureOr<ast::VariableDecl *> Parser::parseResultDecl(
unsigned resultNum) {
1133 StringRef name = curToken.getSpelling();
1134 SMRange nameLoc = curToken.getLoc();
1138 "expected `:` before result constraint")))
1141 FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1145 return createArgOrResultVariableDecl(name, nameLoc, *cst);
1151 FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1155 return createArgOrResultVariableDecl(
"", cst->referenceLoc, *cst);
1158 FailureOr<ast::UserConstraintDecl *>
1159 Parser::parseUserConstraintDecl(
bool isInline) {
1162 return parseUserConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1163 [&](
auto &&...args) {
1164 return this->parseUserPDLLConstraintDecl(args...);
1166 ParserContext::Constraint,
"constraint", isInline);
1169 FailureOr<ast::UserConstraintDecl *> Parser::parseInlineUserConstraintDecl() {
1170 FailureOr<ast::UserConstraintDecl *> decl =
1171 parseUserConstraintDecl(
true);
1172 if (
failed(decl) ||
failed(checkDefineNamedDecl((*decl)->getName())))
1175 curDeclScope->add(*decl);
1179 FailureOr<ast::UserConstraintDecl *> Parser::parseUserPDLLConstraintDecl(
1185 pushDeclScope(argumentScope);
1191 FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1192 [&](
ast::Stmt *&stmt) -> LogicalResult {
1193 ast::Expr *stmtExpr = dyn_cast<ast::Expr>(stmt);
1196 "expected `Constraint` lambda body to contain a "
1197 "single expression");
1207 FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1213 auto bodyIt = body->
begin(), bodyE = body->
end();
1214 for (; bodyIt != bodyE; ++bodyIt)
1215 if (isa<ast::ReturnStmt>(*bodyIt))
1217 if (
failed(validateUserConstraintOrRewriteReturn(
1218 "Constraint", body, bodyIt, bodyE, results, resultType)))
1223 return createUserPDLLConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1224 name, arguments, results, resultType, body);
1227 FailureOr<ast::UserRewriteDecl *> Parser::parseUserRewriteDecl(
bool isInline) {
1230 return parseUserConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1231 [&](
auto &&...args) {
return this->parseUserPDLLRewriteDecl(args...); },
1232 ParserContext::Rewrite,
"rewrite", isInline);
1235 FailureOr<ast::UserRewriteDecl *> Parser::parseInlineUserRewriteDecl() {
1236 FailureOr<ast::UserRewriteDecl *> decl =
1237 parseUserRewriteDecl(
true);
1238 if (
failed(decl) ||
failed(checkDefineNamedDecl((*decl)->getName())))
1241 curDeclScope->add(*decl);
1245 FailureOr<ast::UserRewriteDecl *> Parser::parseUserPDLLRewriteDecl(
1251 curDeclScope = argumentScope;
1254 FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1255 [&](
ast::Stmt *&statement) -> LogicalResult {
1256 if (isa<ast::OpRewriteStmt>(statement))
1259 ast::Expr *statementExpr = dyn_cast<ast::Expr>(statement);
1260 if (!statementExpr) {
1263 "expected `Rewrite` lambda body to contain a single expression "
1264 "or an operation rewrite statement; such as `erase`, "
1265 "`replace`, or `rewrite`");
1276 FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1284 auto bodyIt = body->
begin(), bodyE = body->
end();
1285 for (; bodyIt != bodyE; ++bodyIt)
1286 if (isa<ast::ReturnStmt>(*bodyIt))
1288 if (
failed(validateUserConstraintOrRewriteReturn(
"Rewrite", body, bodyIt,
1289 bodyE, results, resultType)))
1291 return createUserPDLLConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1292 name, arguments, results, resultType, body);
1295 template <
typename T,
typename ParseUserPDLLDeclFnT>
1296 FailureOr<T *> Parser::parseUserConstraintOrRewriteDecl(
1297 ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
1298 StringRef anonymousNamePrefix,
bool isInline) {
1299 SMRange loc = curToken.getLoc();
1301 llvm::SaveAndRestore saveCtx(parserContext, declContext);
1309 return emitError(
"expected identifier name");
1313 std::string anonName =
1314 llvm::formatv(
"<anonymous_{0}_{1}>", anonymousNamePrefix,
1315 anonymousDeclNameCounter++)
1328 if (
failed(parseUserConstraintOrRewriteSignature(arguments, results,
1329 argumentScope, resultType)))
1335 return parseUserPDLLFn(*name, isInline, arguments, argumentScope, results,
1339 return parseUserNativeConstraintOrRewriteDecl<T>(*name, isInline, arguments,
1340 results, resultType);
1343 template <
typename T>
1344 FailureOr<T *> Parser::parseUserNativeConstraintOrRewriteDecl(
1349 std::string codeStrStorage;
1350 std::optional<StringRef> optCodeStr;
1351 if (curToken.isString()) {
1352 codeStrStorage = curToken.getStringValue();
1353 optCodeStr = codeStrStorage;
1355 }
else if (isInline) {
1357 "external declarations must be declared in global scope");
1362 "expected `;` after native declaration")))
1364 return T::createNative(ctx, name, arguments, results, optCodeStr, resultType);
1367 LogicalResult Parser::parseUserConstraintOrRewriteSignature(
1375 argumentScope = pushDeclScope();
1378 FailureOr<ast::VariableDecl *> argument = parseArgumentDecl();
1381 arguments.emplace_back(*argument);
1391 auto parseResultFn = [&]() -> LogicalResult {
1392 FailureOr<ast::VariableDecl *> result = parseResultDecl(results.size());
1395 results.emplace_back(*result);
1402 if (
failed(parseResultFn()))
1409 }
else if (
failed(parseResultFn())) {
1416 resultType = createUserConstraintRewriteResultType(results);
1419 if (results.size() == 1 && !results.front()->getName().getName().empty()) {
1421 results.front()->getLoc(),
1422 "cannot create a single-element tuple with an element label");
1427 LogicalResult Parser::validateUserConstraintOrRewriteReturn(
1433 if (bodyIt != bodyE) {
1435 if (std::next(bodyIt) != bodyE) {
1437 (*std::next(bodyIt))->getLoc(),
1438 llvm::formatv(
"`return` terminated the `{0}` body, but found "
1439 "trailing statements afterwards",
1445 }
else if (!results.empty()) {
1447 {body->getLoc().End, body->getLoc().End},
1448 llvm::formatv(
"missing return in a `{0}` expected to return `{1}`",
1449 declType, resultType));
1454 FailureOr<ast::CompoundStmt *> Parser::parsePatternLambdaBody() {
1455 return parseLambdaBody([&](
ast::Stmt *&statement) -> LogicalResult {
1456 if (isa<ast::OpRewriteStmt>(statement))
1460 "expected Pattern lambda body to contain a single operation "
1461 "rewrite statement, such as `erase`, `replace`, or `rewrite`");
1465 FailureOr<ast::Decl *> Parser::parsePatternDecl() {
1466 SMRange loc = curToken.getLoc();
1468 llvm::SaveAndRestore saveCtx(parserContext, ParserContext::PatternMatch);
1478 ParsedPatternMetadata metadata;
1487 FailureOr<ast::CompoundStmt *> bodyResult = parsePatternLambdaBody();
1493 return emitError(
"expected `{` or `=>` to start pattern body");
1494 FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1500 auto bodyIt = body->
begin(), bodyE = body->
end();
1501 for (; bodyIt != bodyE; ++bodyIt) {
1502 if (isa<ast::ReturnStmt>(*bodyIt)) {
1504 "`return` statements are only permitted within a "
1505 "`Constraint` or `Rewrite` body");
1508 if (isa<ast::OpRewriteStmt>(*bodyIt))
1511 if (bodyIt == bodyE) {
1513 "expected Pattern body to terminate with an operation "
1514 "rewrite statement, such as `erase`");
1516 if (std::next(bodyIt) != bodyE) {
1517 return emitError((*std::next(bodyIt))->getLoc(),
1518 "Pattern body was terminated by an operation "
1519 "rewrite statement, but found trailing statements");
1523 return createPatternDecl(loc, name, metadata, body);
1527 Parser::parsePatternDeclMetadata(ParsedPatternMetadata &metadata) {
1528 std::optional<SMRange> benefitLoc;
1529 std::optional<SMRange> hasBoundedRecursionLoc;
1534 return codeCompletePatternMetadata();
1537 return emitError(
"expected pattern metadata identifier");
1538 StringRef metadataStr = curToken.getSpelling();
1539 SMRange metadataLoc = curToken.getLoc();
1543 if (metadataStr ==
"benefit") {
1545 return emitErrorAndNote(metadataLoc,
1546 "pattern benefit has already been specified",
1547 *benefitLoc,
"see previous definition here");
1550 "expected `(` before pattern benefit")))
1553 uint16_t benefitValue = 0;
1555 return emitError(
"expected integral pattern benefit");
1556 if (curToken.getSpelling().getAsInteger(10, benefitValue))
1558 "expected pattern benefit to fit within a 16-bit integer");
1561 metadata.benefit = benefitValue;
1562 benefitLoc = metadataLoc;
1565 parseToken(
Token::r_paren,
"expected `)` after pattern benefit")))
1571 if (metadataStr ==
"recursion") {
1572 if (hasBoundedRecursionLoc) {
1573 return emitErrorAndNote(
1575 "pattern recursion metadata has already been specified",
1576 *hasBoundedRecursionLoc,
"see previous definition here");
1578 metadata.hasBoundedRecursion =
true;
1579 hasBoundedRecursionLoc = metadataLoc;
1583 return emitError(metadataLoc,
"unknown pattern metadata");
1589 FailureOr<ast::Expr *> Parser::parseTypeConstraintExpr() {
1592 FailureOr<ast::Expr *> typeExpr = parseExpr();
1595 "expected `>` after variable type constraint")))
1600 LogicalResult Parser::checkDefineNamedDecl(
const ast::Name &name) {
1601 assert(curDeclScope &&
"defining decl outside of a decl scope");
1603 return emitErrorAndNote(
1604 name.
getLoc(),
"`" + name.
getName() +
"` has already been defined",
1605 lastDecl->getName()->getLoc(),
"see previous definition here");
1610 FailureOr<ast::VariableDecl *>
1611 Parser::defineVariableDecl(StringRef name, SMRange nameLoc,
ast::Type type,
1614 assert(curDeclScope &&
"defining variable outside of decl scope");
1619 if (name.empty() || name ==
"_") {
1623 if (
failed(checkDefineNamedDecl(nameDecl)))
1628 curDeclScope->add(varDecl);
1632 FailureOr<ast::VariableDecl *>
1633 Parser::defineVariableDecl(StringRef name, SMRange nameLoc,
ast::Type type,
1635 return defineVariableDecl(name, nameLoc, type,
nullptr,
1639 LogicalResult Parser::parseVariableDeclConstraintList(
1641 std::optional<SMRange> typeConstraint;
1642 auto parseSingleConstraint = [&] {
1643 FailureOr<ast::ConstraintRef> constraint = parseConstraint(
1644 typeConstraint, constraints,
true);
1647 constraints.push_back(*constraint);
1653 return parseSingleConstraint();
1656 if (
failed(parseSingleConstraint()))
1659 return parseToken(
Token::r_square,
"expected `]` after constraint list");
1662 FailureOr<ast::ConstraintRef>
1663 Parser::parseConstraint(std::optional<SMRange> &typeConstraint,
1665 bool allowInlineTypeConstraints) {
1666 auto parseTypeConstraint = [&](
ast::Expr *&typeExpr) -> LogicalResult {
1667 if (!allowInlineTypeConstraints) {
1670 "inline `Attr`, `Value`, and `ValueRange` type constraints are not "
1671 "permitted on arguments or results");
1674 return emitErrorAndNote(
1676 "the type of this variable has already been constrained",
1677 *typeConstraint,
"see previous constraint location here");
1678 FailureOr<ast::Expr *> constraintExpr = parseTypeConstraintExpr();
1679 if (
failed(constraintExpr))
1681 typeExpr = *constraintExpr;
1682 typeConstraint = typeExpr->getLoc();
1686 SMRange loc = curToken.getLoc();
1687 switch (curToken.getKind()) {
1703 FailureOr<ast::OpNameDecl *> opName =
1704 parseWrappedOperationName(
true);
1743 FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1749 StringRef constraintName = curToken.getSpelling();
1755 return emitError(loc,
"unknown reference to constraint `" +
1756 constraintName +
"`");
1760 if (
auto *cst = dyn_cast<ast::ConstraintDecl>(cstDecl))
1763 return emitErrorAndNote(
1764 loc,
"invalid reference to non-constraint", cstDecl->
getLoc(),
1765 "see the definition of `" + constraintName +
"` here");
1771 if (
failed(validateVariableConstraints(existingConstraints, inferredType)))
1774 return codeCompleteConstraintName(inferredType, allowInlineTypeConstraints);
1779 return emitError(loc,
"expected identifier constraint");
1782 FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() {
1783 std::optional<SMRange> typeConstraint;
1784 return parseConstraint(typeConstraint, {},
1792 FailureOr<ast::Expr *> Parser::parseExpr() {
1794 return parseUnderscoreExpr();
1797 FailureOr<ast::Expr *> lhsExpr;
1798 switch (curToken.getKind()) {
1800 lhsExpr = parseAttributeExpr();
1803 lhsExpr = parseInlineConstraintLambdaExpr();
1806 lhsExpr = parseNegatedExpr();
1809 lhsExpr = parseIdentifierExpr();
1812 lhsExpr = parseOperationExpr();
1815 lhsExpr = parseInlineRewriteLambdaExpr();
1818 lhsExpr = parseTypeExpr();
1821 lhsExpr = parseTupleExpr();
1824 return emitError(
"expected expression");
1831 switch (curToken.getKind()) {
1833 lhsExpr = parseMemberAccessExpr(*lhsExpr);
1836 lhsExpr = parseCallExpr(*lhsExpr);
1846 FailureOr<ast::Expr *> Parser::parseAttributeExpr() {
1847 SMRange loc = curToken.getLoc();
1854 return parseIdentifierExpr();
1857 if (!curToken.isString())
1858 return emitError(
"expected string literal containing MLIR attribute");
1859 std::string attrExpr = curToken.getStringValue();
1862 loc.End = curToken.getEndLoc();
1864 parseToken(
Token::greater,
"expected `>` after attribute literal")))
1869 FailureOr<ast::Expr *> Parser::parseCallExpr(
ast::Expr *parentExpr,
1879 codeCompleteCallSignature(parentExpr, arguments.size());
1883 FailureOr<ast::Expr *> argument = parseExpr();
1886 arguments.push_back(*argument);
1890 SMRange loc(parentExpr->
getLoc().Start, curToken.getEndLoc());
1894 return createCallExpr(loc, parentExpr, arguments, isNegated);
1897 FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) {
1898 ast::Decl *decl = curDeclScope->lookup(name);
1900 return emitError(loc,
"undefined reference to `" + name +
"`");
1902 return createDeclRefExpr(loc, decl);
1905 FailureOr<ast::Expr *> Parser::parseIdentifierExpr() {
1906 StringRef name = curToken.getSpelling();
1907 SMRange nameLoc = curToken.getLoc();
1914 if (
failed(parseVariableDeclConstraintList(constraints)))
1917 if (
failed(validateVariableConstraints(constraints, type)))
1919 return createInlineVariableExpr(type, name, nameLoc, constraints);
1922 return parseDeclRefExpr(name, nameLoc);
1925 FailureOr<ast::Expr *> Parser::parseInlineConstraintLambdaExpr() {
1926 FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1934 FailureOr<ast::Expr *> Parser::parseInlineRewriteLambdaExpr() {
1935 FailureOr<ast::UserRewriteDecl *> decl = parseInlineUserRewriteDecl();
1943 FailureOr<ast::Expr *> Parser::parseMemberAccessExpr(
ast::Expr *parentExpr) {
1944 SMRange dotLoc = curToken.getLoc();
1949 return codeCompleteMemberAccess(parentExpr);
1952 Token memberNameTok = curToken;
1955 return emitError(dotLoc,
"expected identifier or numeric member name");
1956 StringRef memberName = memberNameTok.
getSpelling();
1957 SMRange loc(parentExpr->
getLoc().Start, curToken.getEndLoc());
1960 return createMemberAccessExpr(parentExpr, memberName, loc);
1963 FailureOr<ast::Expr *> Parser::parseNegatedExpr() {
1967 return emitError(
"expected native constraint");
1968 FailureOr<ast::Expr *> identifierExpr = parseIdentifierExpr();
1969 if (
failed(identifierExpr))
1972 return emitError(
"expected `(` after function name");
1973 return parseCallExpr(*identifierExpr,
true);
1976 FailureOr<ast::OpNameDecl *> Parser::parseOperationName(
bool allowEmptyName) {
1977 SMRange loc = curToken.getLoc();
1981 return codeCompleteDialectName();
1987 return emitError(
"expected dialect namespace");
1989 StringRef name = curToken.getSpelling();
1993 if (
failed(parseToken(
Token::dot,
"expected `.` after dialect namespace")))
1998 return codeCompleteOperationName(name);
2001 return emitError(
"expected operation name after dialect namespace");
2003 name = StringRef(name.data(), name.size() + 1);
2005 name = StringRef(name.data(), name.size() + curToken.getSpelling().size());
2006 loc.End = curToken.getEndLoc();
2009 curToken.isKeyword());
2013 FailureOr<ast::OpNameDecl *>
2014 Parser::parseWrappedOperationName(
bool allowEmptyName) {
2018 FailureOr<ast::OpNameDecl *> opNameDecl = parseOperationName(allowEmptyName);
2027 FailureOr<ast::Expr *>
2028 Parser::parseOperationExpr(OpResultTypeContext inputResultTypeContext) {
2029 SMRange loc = curToken.getLoc();
2036 return parseIdentifierExpr();
2042 bool allowEmptyName = parserContext != ParserContext::Rewrite;
2043 FailureOr<ast::OpNameDecl *> opNameDecl =
2044 parseWrappedOperationName(allowEmptyName);
2047 std::optional<StringRef> opName = (*opNameDecl)->getName();
2052 FailureOr<ast::VariableDecl *> rangeVar =
2054 assert(succeeded(rangeVar) &&
"expected range variable to be valid");
2065 if (parserContext != ParserContext::Rewrite) {
2066 operands.push_back(createImplicitRangeVar(
2074 codeCompleteOperationOperandsSignature(opName, operands.size());
2078 FailureOr<ast::Expr *> operand = parseExpr();
2081 operands.push_back(*operand);
2085 "expected `)` after operation operand list")))
2093 FailureOr<ast::NamedAttributeDecl *> decl =
2094 parseNamedAttributeDecl(opName);
2097 attributes.emplace_back(*decl);
2101 "expected `}` after operation attribute list")))
2107 OpResultTypeContext resultTypeContext = inputResultTypeContext;
2112 "expected `(` before operation result type list")))
2120 resultTypeContext = OpResultTypeContext::Explicit;
2127 codeCompleteOperationResultsSignature(opName, resultTypes.size());
2131 FailureOr<ast::Expr *> resultTypeExpr = parseExpr();
2132 if (
failed(resultTypeExpr))
2134 resultTypes.push_back(*resultTypeExpr);
2138 "expected `)` after operation result type list")))
2141 }
else if (parserContext != ParserContext::Rewrite) {
2146 resultTypes.push_back(createImplicitRangeVar(
2148 }
else if (resultTypeContext == OpResultTypeContext::Explicit) {
2151 resultTypeContext = OpResultTypeContext::Interface;
2154 return createOperationExpr(loc, *opNameDecl, resultTypeContext, operands,
2155 attributes, resultTypes);
2158 FailureOr<ast::Expr *> Parser::parseTupleExpr() {
2159 SMRange loc = curToken.getLoc();
2168 StringRef elementName;
2170 Token elementNameTok = curToken;
2178 auto elementNameIt =
2179 usedNames.try_emplace(elementName, elementNameTok.
getLoc());
2180 if (!elementNameIt.second) {
2181 return emitErrorAndNote(
2183 llvm::formatv(
"duplicate tuple element label `{0}`",
2185 elementNameIt.first->getSecond(),
2186 "see previous label use here");
2191 resetToken(elementNameTok.
getLoc());
2194 elementNames.push_back(elementName);
2197 FailureOr<ast::Expr *> element = parseExpr();
2200 elements.push_back(*element);
2203 loc.End = curToken.getEndLoc();
2205 parseToken(
Token::r_paren,
"expected `)` after tuple element list")))
2207 return createTupleExpr(loc, elements, elementNames);
2210 FailureOr<ast::Expr *> Parser::parseTypeExpr() {
2211 SMRange loc = curToken.getLoc();
2218 return parseIdentifierExpr();
2221 if (!curToken.isString())
2222 return emitError(
"expected string literal containing MLIR type");
2223 std::string attrExpr = curToken.getStringValue();
2226 loc.End = curToken.getEndLoc();
2232 FailureOr<ast::Expr *> Parser::parseUnderscoreExpr() {
2233 StringRef name = curToken.getSpelling();
2234 SMRange nameLoc = curToken.getLoc();
2243 if (
failed(parseVariableDeclConstraintList(constraints)))
2247 if (
failed(validateVariableConstraints(constraints, type)))
2249 return createInlineVariableExpr(type, name, nameLoc, constraints);
2256 FailureOr<ast::Stmt *> Parser::parseStmt(
bool expectTerminalSemicolon) {
2257 FailureOr<ast::Stmt *> stmt;
2258 switch (curToken.getKind()) {
2260 stmt = parseEraseStmt();
2263 stmt = parseLetStmt();
2266 stmt = parseReplaceStmt();
2269 stmt = parseReturnStmt();
2272 stmt = parseRewriteStmt();
2279 (expectTerminalSemicolon &&
2285 FailureOr<ast::CompoundStmt *> Parser::parseCompoundStmt() {
2286 SMLoc startLoc = curToken.getStartLoc();
2293 FailureOr<ast::Stmt *> statement = parseStmt();
2295 return popDeclScope(), failure();
2296 statements.push_back(*statement);
2301 SMRange location(startLoc, curToken.getEndLoc());
2307 FailureOr<ast::EraseStmt *> Parser::parseEraseStmt() {
2308 if (parserContext == ParserContext::Constraint)
2309 return emitError(
"`erase` cannot be used within a Constraint");
2310 SMRange loc = curToken.getLoc();
2314 FailureOr<ast::Expr *> rootOp = parseExpr();
2318 return createEraseStmt(loc, *rootOp);
2321 FailureOr<ast::LetStmt *> Parser::parseLetStmt() {
2322 SMRange loc = curToken.getLoc();
2326 SMRange varLoc = curToken.getLoc();
2331 "`_` may only be used to define \"inline\" variables");
2334 "expected identifier after `let` to name a new variable");
2336 StringRef varName = curToken.getSpelling();
2342 failed(parseVariableDeclConstraintList(constraints)))
2348 FailureOr<ast::Expr *> initOrFailure = parseExpr();
2349 if (
failed(initOrFailure))
2351 initializer = *initOrFailure;
2356 LogicalResult result =
2360 if (cst->getTypeExpr()) {
2362 constraint.referenceLoc,
2363 "type constraints are not permitted on variables with "
2368 .Default(success());
2374 FailureOr<ast::VariableDecl *> varDecl =
2375 createVariableDecl(varName, varLoc, initializer, constraints);
2381 FailureOr<ast::ReplaceStmt *> Parser::parseReplaceStmt() {
2382 if (parserContext == ParserContext::Constraint)
2383 return emitError(
"`replace` cannot be used within a Constraint");
2384 SMRange loc = curToken.getLoc();
2388 FailureOr<ast::Expr *> rootOp = parseExpr();
2393 parseToken(
Token::kw_with,
"expected `with` after root operation")))
2397 llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite);
2404 loc,
"expected at least one replacement value, consider using "
2405 "`erase` if no replacement values are desired");
2409 FailureOr<ast::Expr *> replExpr = parseExpr();
2412 replValues.emplace_back(*replExpr);
2416 "expected `)` after replacement values")))
2421 FailureOr<ast::Expr *> replExpr;
2423 replExpr = parseOperationExpr(OpResultTypeContext::Replacement);
2425 replExpr = parseExpr();
2428 replValues.emplace_back(*replExpr);
2431 return createReplaceStmt(loc, *rootOp, replValues);
2434 FailureOr<ast::ReturnStmt *> Parser::parseReturnStmt() {
2435 SMRange loc = curToken.getLoc();
2439 FailureOr<ast::Expr *> resultExpr = parseExpr();
2446 FailureOr<ast::RewriteStmt *> Parser::parseRewriteStmt() {
2447 if (parserContext == ParserContext::Constraint)
2448 return emitError(
"`rewrite` cannot be used within a Constraint");
2449 SMRange loc = curToken.getLoc();
2453 FailureOr<ast::Expr *> rootOp = parseExpr();
2461 return emitError(
"expected `{` to start rewrite body");
2464 llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite);
2466 FailureOr<ast::CompoundStmt *> rewriteBody = parseCompoundStmt();
2471 for (
const ast::Stmt *stmt : (*rewriteBody)->getChildren()) {
2472 if (isa<ast::ReturnStmt>(stmt)) {
2474 "`return` statements are only permitted within a "
2475 "`Constraint` or `Rewrite` body");
2479 return createRewriteStmt(loc, *rootOp, *rewriteBody);
2492 if (
auto *init = dyn_cast<ast::DeclRefExpr>(node))
2493 node = init->getDecl();
2494 return dyn_cast<ast::CallableDecl>(node);
2497 FailureOr<ast::PatternDecl *>
2498 Parser::createPatternDecl(SMRange loc,
const ast::Name *name,
2499 const ParsedPatternMetadata &metadata,
2502 metadata.hasBoundedRecursion, body);
2505 ast::Type Parser::createUserConstraintRewriteResultType(
2508 if (results.size() == 1)
2509 return results[0]->getType();
2513 auto resultTypes = llvm::map_range(
2514 results, [&](
const auto *result) {
return result->getType(); });
2515 auto resultNames = llvm::map_range(
2516 results, [&](
const auto *result) {
return result->getName().getName(); });
2518 llvm::to_vector(resultNames));
2521 template <
typename T>
2522 FailureOr<T *> Parser::createUserPDLLConstraintOrRewriteDecl(
2527 if (
auto *retStmt = dyn_cast<ast::ReturnStmt>(body->
getChildren().back())) {
2528 ast::Expr *resultExpr = retStmt->getResultExpr();
2533 if (results.empty())
2534 resultType = resultExpr->
getType();
2535 else if (
failed(convertExpressionTo(resultExpr, resultType)))
2538 retStmt->setResultExpr(resultExpr);
2541 return T::createPDLL(ctx, name, arguments, results, body, resultType);
2544 FailureOr<ast::VariableDecl *>
2545 Parser::createVariableDecl(StringRef name, SMRange loc,
ast::Expr *initializer,
2550 if (
failed(validateVariableConstraints(constraints, type)))
2557 type = initializer->
getType();
2560 else if (
failed(convertExpressionTo(initializer, type)))
2566 return emitErrorAndNote(
2567 loc,
"unable to infer type for variable `" + name +
"`", loc,
2568 "the type of a variable must be inferable from the constraint "
2569 "list or the initializer");
2573 if (isa<ast::ConstraintType, ast::RewriteType>(type)) {
2575 loc, llvm::formatv(
"unable to define variable of `{0}` type", type));
2579 FailureOr<ast::VariableDecl *> varDecl =
2580 defineVariableDecl(name, loc, type, initializer, constraints);
2587 FailureOr<ast::VariableDecl *>
2588 Parser::createArgOrResultVariableDecl(StringRef name, SMRange loc,
2591 if (
failed(validateVariableConstraint(constraint, argType)))
2593 return defineVariableDecl(name, loc, argType, constraint);
2600 if (
failed(validateVariableConstraint(ref, inferredType)))
2608 if (
const auto *cst = dyn_cast<ast::AttrConstraintDecl>(ref.
constraint)) {
2609 if (
const ast::Expr *typeExpr = cst->getTypeExpr()) {
2610 if (
failed(validateTypeConstraintExpr(typeExpr)))
2614 }
else if (
const auto *cst =
2615 dyn_cast<ast::OpConstraintDecl>(ref.
constraint)) {
2618 }
else if (isa<ast::TypeConstraintDecl>(ref.
constraint)) {
2619 constraintType = typeTy;
2620 }
else if (isa<ast::TypeRangeConstraintDecl>(ref.
constraint)) {
2621 constraintType = typeRangeTy;
2622 }
else if (
const auto *cst =
2623 dyn_cast<ast::ValueConstraintDecl>(ref.
constraint)) {
2624 if (
const ast::Expr *typeExpr = cst->getTypeExpr()) {
2625 if (
failed(validateTypeConstraintExpr(typeExpr)))
2628 constraintType = valueTy;
2629 }
else if (
const auto *cst =
2630 dyn_cast<ast::ValueRangeConstraintDecl>(ref.
constraint)) {
2631 if (
const ast::Expr *typeExpr = cst->getTypeExpr()) {
2632 if (
failed(validateTypeRangeConstraintExpr(typeExpr)))
2635 constraintType = valueRangeTy;
2636 }
else if (
const auto *cst =
2637 dyn_cast<ast::UserConstraintDecl>(ref.
constraint)) {
2639 if (inputs.size() != 1) {
2641 "`Constraint`s applied via a variable constraint "
2642 "list must take a single input, but got " +
2643 Twine(inputs.size()),
2645 "see definition of constraint here");
2647 constraintType = inputs.front()->getType();
2649 llvm_unreachable(
"unknown constraint type");
2654 if (!inferredType) {
2655 inferredType = constraintType;
2657 inferredType = mergedTy;
2660 llvm::formatv(
"constraint type `{0}` is incompatible "
2661 "with the previously inferred type `{1}`",
2662 constraintType, inferredType));
2667 LogicalResult Parser::validateTypeConstraintExpr(
const ast::Expr *typeExpr) {
2669 if (typeExprType != typeTy) {
2671 "expected expression of `Type` in type constraint");
2677 Parser::validateTypeRangeConstraintExpr(
const ast::Expr *typeExpr) {
2679 if (typeExprType != typeRangeTy) {
2681 "expected expression of `TypeRange` in type constraint");
2690 FailureOr<ast::CallExpr *>
2691 Parser::createCallExpr(SMRange loc,
ast::Expr *parentExpr,
2696 if (!callableDecl) {
2698 llvm::formatv(
"expected a reference to a callable "
2699 "`Constraint` or `Rewrite`, but got: `{0}`",
2702 if (parserContext == ParserContext::Rewrite) {
2703 if (isa<ast::UserConstraintDecl>(callableDecl))
2705 loc,
"unable to invoke `Constraint` within a rewrite section");
2707 return emitError(loc,
"unable to negate a Rewrite");
2709 if (isa<ast::UserRewriteDecl>(callableDecl))
2711 "unable to invoke `Rewrite` within a match section");
2712 if (isNegated && cast<ast::UserConstraintDecl>(callableDecl)->getBody())
2713 return emitError(loc,
"unable to negate non native constraints");
2719 if (callArgs.size() != arguments.size()) {
2720 return emitErrorAndNote(
2722 llvm::formatv(
"invalid number of arguments for {0} call; expected "
2727 llvm::formatv(
"see the definition of {0} here",
2733 diag.attachNote(llvm::formatv(
"see the definition of `{0}` here",
2737 for (
auto it : llvm::zip(callArgs, arguments)) {
2738 if (
failed(convertExpressionTo(std::get<1>(it), std::get<0>(it)->
getType(),
2747 FailureOr<ast::DeclRefExpr *> Parser::createDeclRefExpr(SMRange loc,
2751 if (isa<ast::ConstraintDecl>(decl))
2753 else if (isa<ast::UserRewriteDecl>(decl))
2755 else if (
auto *varDecl = dyn_cast<ast::VariableDecl>(decl))
2756 declType = varDecl->getType();
2758 return emitError(loc,
"invalid reference to `" +
2764 FailureOr<ast::DeclRefExpr *>
2765 Parser::createInlineVariableExpr(
ast::Type type, StringRef name, SMRange loc,
2767 FailureOr<ast::VariableDecl *> decl =
2768 defineVariableDecl(name, loc, type, constraints);
2774 FailureOr<ast::MemberAccessExpr *>
2775 Parser::createMemberAccessExpr(
ast::Expr *parentExpr, StringRef name,
2778 FailureOr<ast::Type> memberType = validateMemberAccess(parentExpr, name, loc);
2785 FailureOr<ast::Type> Parser::validateMemberAccess(
ast::Expr *parentExpr,
2786 StringRef name, SMRange loc) {
2790 return valueRangeTy;
2794 auto results = odsOp->getResults();
2798 if (llvm::isDigit(name[0]) && !name.getAsInteger(10, index) &&
2799 index < results.size()) {
2800 return results[index].isVariadic() ? valueRangeTy : valueTy;
2804 const auto *it = llvm::find_if(results, [&](
const auto &result) {
2805 return result.getName() == name;
2807 if (it != results.end())
2808 return it->isVariadic() ? valueRangeTy : valueTy;
2809 }
else if (llvm::isDigit(name[0])) {
2814 }
else if (
auto tupleType = dyn_cast<ast::TupleType>(parentType)) {
2817 if (llvm::isDigit(name[0]) && !name.getAsInteger(10, index) &&
2818 index < tupleType.size()) {
2819 return tupleType.getElementTypes()[index];
2823 auto elementNames = tupleType.getElementNames();
2824 const auto *it = llvm::find(elementNames, name);
2825 if (it != elementNames.end())
2826 return tupleType.getElementTypes()[it - elementNames.begin()];
2830 llvm::formatv(
"invalid member access `{0}` on expression of type `{1}`",
2834 FailureOr<ast::OperationExpr *> Parser::createOperationExpr(
2836 OpResultTypeContext resultTypeContext,
2840 std::optional<StringRef> opNameRef = name->
getName();
2844 if (
failed(validateOperationOperands(loc, opNameRef, odsOp, operands)))
2850 ast::Type attrType = attr->getValue()->getType();
2851 if (!isa<ast::AttributeType>(attrType)) {
2853 attr->getValue()->getLoc(),
2854 llvm::formatv(
"expected `Attr` expression, but got `{0}`", attrType));
2859 (resultTypeContext == OpResultTypeContext::Explicit || results.empty()) &&
2860 "unexpected inferrence when results were explicitly specified");
2864 if (resultTypeContext == OpResultTypeContext::Explicit) {
2865 if (
failed(validateOperationResults(loc, opNameRef, odsOp, results)))
2869 }
else if (resultTypeContext == OpResultTypeContext::Interface) {
2871 "expected valid operation name when inferring operation results");
2872 checkOperationResultTypeInferrence(loc, *opNameRef, odsOp);
2880 Parser::validateOperationOperands(SMRange loc, std::optional<StringRef> name,
2883 return validateOperationOperandsOrResults(
2884 "operand", loc, odsOp ? odsOp->
getLoc() : std::optional<SMRange>(), name,
2887 valueTy, valueRangeTy);
2891 Parser::validateOperationResults(SMRange loc, std::optional<StringRef> name,
2894 return validateOperationOperandsOrResults(
2895 "result", loc, odsOp ? odsOp->
getLoc() : std::optional<SMRange>(), name,
2898 typeTy, typeRangeTy);
2901 void Parser::checkOperationResultTypeInferrence(SMRange loc, StringRef opName,
2912 "operation result types are marked to be inferred, but "
2913 "`{0}` is unknown. Ensure that `{0}` supports zero "
2914 "results or implements `InferTypeOpInterface`. Include "
2915 "the ODS definition of this operation to remove this warning.",
2924 bool requiresInferrence =
2926 return !result.isVariableLength();
2931 llvm::formatv(
"operation result types are marked to be inferred, but "
2932 "`{0}` does not provide an implementation of "
2933 "`InferTypeOpInterface`. Ensure that `{0}` attaches "
2934 "`InferTypeOpInterface` at runtime, or add support to "
2935 "the ODS definition to remove this warning.",
2937 diag->attachNote(llvm::formatv(
"see the definition of `{0}` here", opName),
2943 LogicalResult Parser::validateOperationOperandsOrResults(
2944 StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
2949 if (values.size() == 1) {
2950 if (
failed(convertExpressionTo(values[0], rangeTy)))
2958 auto emitSizeMismatchError = [&] {
2959 return emitErrorAndNote(
2961 llvm::formatv(
"invalid number of {0} groups for `{1}`; expected "
2963 groupName, *name, odsValues.size(), values.size()),
2964 *odsOpLoc, llvm::formatv(
"see the definition of `{0}` here", *name));
2968 if (values.empty()) {
2970 if (odsValues.empty())
2975 unsigned numVariadic = 0;
2976 for (
const auto &odsValue : odsValues) {
2977 if (!odsValue.isVariableLength())
2978 return emitSizeMismatchError();
2984 if (parserContext != ParserContext::Rewrite)
2991 if (numVariadic == 1)
2996 for (
unsigned i = 0, e = odsValues.size(); i < e; ++i) {
3005 if (odsValues.size() != values.size())
3006 return emitSizeMismatchError();
3009 diag.attachNote(llvm::formatv(
"see the definition of `{0}` here", *name),
3012 for (
unsigned i = 0, e = values.size(); i < e; ++i) {
3013 ast::Type expectedType = odsValues[i].isVariadic() ? rangeTy : singleTy;
3014 if (
failed(convertExpressionTo(values[i], expectedType, diagFn)))
3023 ast::Type valueExprType = valueExpr->getType();
3026 if (valueExprType == rangeTy || valueExprType == singleTy)
3032 if (singleTy == valueTy) {
3033 if (isa<ast::OperationType>(valueExprType)) {
3034 valueExpr = convertOpToValue(valueExpr);
3040 if (succeeded(convertExpressionTo(valueExpr, rangeTy)))
3044 valueExpr->getLoc(),
3046 "expected `{0}` or `{1}` convertible expression, but got `{2}`",
3047 singleTy, rangeTy, valueExprType));
3052 FailureOr<ast::TupleExpr *>
3055 for (
const ast::Expr *element : elements) {
3057 if (isa<ast::ConstraintType, ast::RewriteType, ast::TupleType>(eleTy)) {
3060 llvm::formatv(
"unable to build a tuple with `{0}` element", eleTy));
3070 FailureOr<ast::EraseStmt *> Parser::createEraseStmt(SMRange loc,
3074 if (!isa<ast::OperationType>(rootType))
3080 FailureOr<ast::ReplaceStmt *>
3081 Parser::createReplaceStmt(SMRange loc,
ast::Expr *rootOp,
3085 if (!isa<ast::OperationType>(rootType)) {
3088 llvm::formatv(
"expected `Op` expression, but got `{0}`", rootType));
3093 bool shouldConvertOpToValues = replValues.size() > 1;
3094 for (
ast::Expr *&replExpr : replValues) {
3095 ast::Type replType = replExpr->getType();
3098 if (isa<ast::OperationType>(replType)) {
3099 if (shouldConvertOpToValues)
3100 replExpr = convertOpToValue(replExpr);
3104 if (replType != valueTy && replType != valueRangeTy) {
3106 llvm::formatv(
"expected `Op`, `Value` or `ValueRange` "
3107 "expression, but got `{0}`",
3115 FailureOr<ast::RewriteStmt *>
3116 Parser::createRewriteStmt(SMRange loc,
ast::Expr *rootOp,
3120 if (!isa<ast::OperationType>(rootType)) {
3123 llvm::formatv(
"expected `Op` expression, but got `{0}`", rootType));
3133 LogicalResult Parser::codeCompleteMemberAccess(
ast::Expr *parentExpr) {
3137 else if (
ast::TupleType tupleType = dyn_cast<ast::TupleType>(parentType))
3143 Parser::codeCompleteAttributeName(std::optional<StringRef> opName) {
3150 Parser::codeCompleteConstraintName(
ast::Type inferredType,
3151 bool allowInlineTypeConstraints) {
3153 inferredType, allowInlineTypeConstraints, curDeclScope);
3157 LogicalResult Parser::codeCompleteDialectName() {
3162 LogicalResult Parser::codeCompleteOperationName(StringRef dialectName) {
3167 LogicalResult Parser::codeCompletePatternMetadata() {
3172 LogicalResult Parser::codeCompleteIncludeFilename(StringRef curPath) {
3177 void Parser::codeCompleteCallSignature(
ast::Node *parent,
3178 unsigned currentNumArgs) {
3186 void Parser::codeCompleteOperationOperandsSignature(
3187 std::optional<StringRef> opName,
unsigned currentNumOperands) {
3189 opName, currentNumOperands);
3192 void Parser::codeCompleteOperationResultsSignature(
3193 std::optional<StringRef> opName,
unsigned currentNumResults) {
3202 FailureOr<ast::Module *>
3204 bool enableDocumentation,
3206 Parser parser(ctx, sourceMgr, enableDocumentation, codeCompleteContext);
3207 return parser.parseModule();
union mlir::linalg::@1244::ArityGroupAndKind::Kind kind
static std::string diag(const llvm::Value &value)
This class breaks up the current file into a token stream.
This represents a token in the MLIR syntax.
bool isKeyword() const
Return true if this is one of the keyword token kinds (e.g. kw_if).
StringRef getSpelling() const
This class provides an abstract interface into the parser for hooking in code completion events.
virtual void codeCompleteConstraintName(ast::Type currentType, bool allowInlineTypeConstraints, const ast::DeclScope *scope)
Signal code completion for a constraint name with an optional decl scope.
virtual void codeCompleteOperationAttributeName(StringRef opName)
Signal code completion for a member access into the given operation type.
virtual void codeCompleteOperationOperandsSignature(std::optional< StringRef > opName, unsigned currentNumOperands)
Signal code completion for the signature of an operation's operands.
virtual void codeCompleteOperationName(StringRef dialectName)
Signal code completion for an operation name in the given dialect.
virtual void codeCompleteOperationResultsSignature(std::optional< StringRef > opName, unsigned currentNumResults)
Signal code completion for the signature of an operation's results.
virtual void codeCompleteDialectName()
Signal code completion for a dialect name.
virtual void codeCompleteOperationMemberAccess(ast::OperationType opType)
Signal code completion for a member access into the given operation type.
virtual void codeCompleteTupleMemberAccess(ast::TupleType tupleType)
Signal code completion for a member access into the given tuple type.
virtual void codeCompletePatternMetadata()
Signal code completion for Pattern metadata.
virtual void codeCompleteCallSignature(const ast::CallableDecl *callable, unsigned currentNumArgs)
Signal code completion for the signature of a callable.
virtual void codeCompleteIncludeFilename(StringRef curPath)
Signal code completion for an include filename.
@ code_complete_string
Token signifying a code completion location within a string.
@ code_complete
Token signifying a code completion location.
@ less
Paired punctuation.
@ kw_Attr
General keywords.
static StringRef getMemberName()
Return the member name used for the "all-results" access.
static AllResultsMemberAccessExpr * create(Context &ctx, SMRange loc, const Expr *parentExpr, Type type)
The class represents an Attribute constraint, and constrains a variable to be an Attribute.
static AttrConstraintDecl * create(Context &ctx, SMRange loc, Expr *typeExpr=nullptr)
static AttributeExpr * create(Context &ctx, SMRange loc, StringRef value)
static AttributeType get(Context &context)
Return an instance of the Attribute type.
static CallExpr * create(Context &ctx, SMRange loc, Expr *callable, ArrayRef< Expr * > arguments, Type resultType, bool isNegated=false)
This decl represents a shared interface for all callable decls.
Type getResultType() const
Return the result type of this decl.
ArrayRef< VariableDecl * > getInputs() const
Return the inputs of this decl.
StringRef getCallableType() const
Return the callable type of this decl.
This statement represents a compound statement, which contains a collection of other statements.
ArrayRef< Stmt * >::iterator begin() const
MutableArrayRef< Stmt * > getChildren()
Return the children of this compound statement.
ArrayRef< Stmt * >::iterator end() const
static CompoundStmt * create(Context &ctx, SMRange location, ArrayRef< Stmt * > children)
This class represents the base of all AST Constraint decls.
static ConstraintType get(Context &context)
Return an instance of the Constraint type.
This class represents the main context of the PDLL AST.
DiagnosticEngine & getDiagEngine()
Return the diagnostic engine of this context.
ods::Context & getODSContext()
Return the ODS context used by the AST.
static DeclRefExpr * create(Context &ctx, SMRange loc, Decl *decl, Type type)
This class represents a scope for named AST decls.
DeclScope * getParentScope()
Return the parent scope of this scope, or nullptr if there is no parent.
void add(Decl *decl)
Add a new decl to the scope.
This class represents the base Decl node.
const Name * getName() const
Return the name of the decl, or nullptr if it doesn't have one.
InFlightDiagnostic emitWarning(SMRange loc, const Twine &msg)
InFlightDiagnostic emitError(SMRange loc, const Twine &msg)
Emit an error to the diagnostic engine.
This class provides a simple implementation of a PDLL diagnostic.
static EraseStmt * create(Context &ctx, SMRange loc, Expr *rootOp)
This class represents a base AST Expression node.
Type getType() const
Return the type of this expression.
This class represents a diagnostic that is inflight and set to be reported.
static LetStmt * create(Context &ctx, SMRange loc, VariableDecl *varDecl)
static MemberAccessExpr * create(Context &ctx, SMRange loc, const Expr *parentExpr, StringRef memberName, Type type)
static Module * create(Context &ctx, SMLoc loc, ArrayRef< Decl * > children)
This Decl represents a NamedAttribute, and contains a string name and attribute value.
static NamedAttributeDecl * create(Context &ctx, const Name &name, Expr *value)
This class represents a base AST node.
SMRange getLoc() const
Return the location of this node.
static OpConstraintDecl * create(Context &ctx, SMRange loc, const OpNameDecl *nameDecl=nullptr)
This Decl represents an OperationName.
std::optional< StringRef > getName() const
Return the name of this operation, or std::nullopt if the name is unknown.
static OpNameDecl * create(Context &ctx, const Name &name)
static OperationExpr * create(Context &ctx, SMRange loc, const ods::Operation *odsOp, const OpNameDecl *nameDecl, ArrayRef< Expr * > operands, ArrayRef< Expr * > resultTypes, ArrayRef< NamedAttributeDecl * > attributes)
This class represents a PDLL type that corresponds to an mlir::Operation.
const ods::Operation * getODSOperation() const
Return the ODS operation that this type refers to, or nullptr if the ODS operation is unknown.
static OperationType get(Context &context, std::optional< StringRef > name=std::nullopt, const ods::Operation *odsOp=nullptr)
Return an instance of the Operation type with an optional operation name.
static PatternDecl * create(Context &ctx, SMRange location, const Name *name, std::optional< uint16_t > benefit, bool hasBoundedRecursion, const CompoundStmt *body)
static RangeExpr * create(Context &ctx, SMRange loc, ArrayRef< Expr * > elements, RangeType type)
This class represents a PDLL type that corresponds to a range of elements with a given element type.
static ReplaceStmt * create(Context &ctx, SMRange loc, Expr *rootOp, ArrayRef< Expr * > replExprs)
static ReturnStmt * create(Context &ctx, SMRange loc, Expr *resultExpr)
static RewriteStmt * create(Context &ctx, SMRange loc, Expr *rootOp, CompoundStmt *rewriteBody)
static RewriteType get(Context &context)
Return an instance of the Rewrite type.
This class represents a base AST Statement node.
static TupleExpr * create(Context &ctx, SMRange loc, ArrayRef< Expr * > elements, ArrayRef< StringRef > elementNames)
This class represents a PDLL tuple type, i.e.
size_t size() const
Return the number of elements within this tuple.
ArrayRef< Type > getElementTypes() const
Return the element types of this tuple.
static TupleType get(Context &context, ArrayRef< Type > elementTypes, ArrayRef< StringRef > elementNames)
Return an instance of the Tuple type.
static TypeConstraintDecl * create(Context &ctx, SMRange loc)
static TypeExpr * create(Context &ctx, SMRange loc, StringRef value)
static TypeRangeConstraintDecl * create(Context &ctx, SMRange loc)
static TypeRangeType get(Context &context)
Return an instance of the TypeRange type.
static TypeType get(Context &context)
Return an instance of the Type type.
Type refineWith(Type other) const
Try to refine this type with the one provided.
static UserConstraintDecl * createNative(Context &ctx, const Name &name, ArrayRef< VariableDecl * > inputs, ArrayRef< VariableDecl * > results, std::optional< StringRef > codeBlock, Type resultType, ArrayRef< StringRef > nativeInputTypes={})
Create a native constraint with the given optional code block.
The class represents a Value constraint, and constrains a variable to be a Value.
static ValueConstraintDecl * create(Context &ctx, SMRange loc, Expr *typeExpr)
The class represents a ValueRange constraint, and constrains a variable to be a ValueRange.
static ValueRangeConstraintDecl * create(Context &ctx, SMRange loc, Expr *typeExpr=nullptr)
static ValueRangeType get(Context &context)
Return an instance of the ValueRange type.
static ValueType get(Context &context)
Return an instance of the Value type.
static VariableDecl * create(Context &ctx, const Name &name, Type type, Expr *initExpr, ArrayRef< ConstraintRef > constraints)
This class contains all of the registered ODS operation classes.
std::pair< Operation *, bool > insertOperation(StringRef name, StringRef summary, StringRef desc, StringRef nativeClassName, bool supportsResultTypeInferrence, SMLoc loc)
Insert a new operation with the context.
const TypeConstraint & insertTypeConstraint(StringRef name, StringRef summary, StringRef cppClass)
Insert a new type constraint with the context.
const AttributeConstraint & insertAttributeConstraint(StringRef name, StringRef summary, StringRef cppClass)
Insert a new attribute constraint with the context.
const Operation * lookupOperation(StringRef name) const
Lookup an operation registered with the given name, or null if no operation with that name is registe...
This class provides an ODS representation of a specific operation operand or result.
This class provides an ODS representation of a specific operation.
SMRange getLoc() const
Return the source location of this operation.
ArrayRef< OperandOrResult > getOperands() const
Returns the operands of this operation.
bool hasResultTypeInferrence() const
Return if the operation is known to support result type inferrence.
ArrayRef< OperandOrResult > getResults() const
Returns the results of this operation.
This class represents a generic ODS Type constraint.
raw_ostream subclass that simplifies indention a sequence of code.
raw_indented_ostream & printReindented(StringRef str, StringRef extraPrefix="")
Prints a string re-indented to the current indent.
StringRef getSummary() const
std::string getUniqueDefName() const
Returns a unique name for the TablGen def of this constraint.
StringRef getDescription() const
std::string getConditionTemplate() const
Format context containing substitutions for special placeholders.
FmtContext & withSelf(Twine subst)
Wrapper class that contains a MLIR op's information (e.g., operands, attributes) defined in TableGen ...
FailureOr< ast::Module * > parsePDLLAST(ast::Context &ctx, llvm::SourceMgr &sourceMgr, bool enableDocumentation=false, CodeCompleteContext *codeCompleteContext=nullptr)
Parse an AST module from the main file of the given source manager.
auto tgfmt(StringRef fmt, const FmtContext *ctx, Ts &&...vals) -> FmtObject< decltype(std::make_tuple(llvm::support::detail::build_format_adapter(std::forward< Ts >(vals))...))>
Formats text by substituting placeholders in format string with replacement parameters.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
This class represents a reference to a constraint, and contains a constraint and the location of the ...
const ConstraintDecl * constraint
This class provides a convenient API for interacting with source names.
StringRef getName() const
Return the raw string name.
SMRange getLoc() const
Get the location of this name.
static const Name & create(Context &ctx, StringRef name, SMRange location)