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/Support/VirtualFileSystem.h"
31#include "llvm/TableGen/Error.h"
32#include "llvm/TableGen/Parser.h"
49 : ctx(ctx), lexer(sourceMgr, ctx.
getDiagEngine(), codeCompleteContext),
50 curToken(lexer.lexToken()), enableDocumentation(enableDocumentation),
55 codeCompleteContext(codeCompleteContext) {}
58 FailureOr<ast::Module *> parseModule();
66 enum class ParserContext {
83 enum class OpResultTypeContext {
102 return (curDeclScope = newScope);
104 void pushDeclScope(
ast::DeclScope *scope) { curDeclScope = scope; }
107 void popDeclScope() { curDeclScope = curDeclScope->
getParentScope(); }
116 LogicalResult convertExpressionTo(
123 LogicalResult convertTupleExpressionTo(
134 const ods::Operation *lookupODSOperation(std::optional<StringRef> opName) {
140 StringRef processDoc(StringRef doc) {
141 return enableDocumentation ? doc : StringRef();
146 std::string processAndFormatDoc(
const Twine &doc) {
147 if (!enableDocumentation)
151 llvm::raw_string_ostream docOS(docStr);
152 std::string tmpDocStr = doc.str();
153 raw_indented_ostream(docOS).printReindented(
154 StringRef(tmpDocStr).rtrim(
" \t"));
162 LogicalResult parseDirective(SmallVectorImpl<ast::Decl *> &decls);
163 LogicalResult parseInclude(SmallVectorImpl<ast::Decl *> &decls);
164 LogicalResult parseTdInclude(StringRef filename, SMRange fileLoc,
165 SmallVectorImpl<ast::Decl *> &decls);
168 void processTdIncludeRecords(
const llvm::RecordKeeper &tdRecords,
169 SmallVectorImpl<ast::Decl *> &decls);
173 template <
typename Constra
intT>
175 createODSNativePDLLConstraintDecl(StringRef name, StringRef codeBlock,
176 SMRange loc, ast::Type type,
177 StringRef nativeType, StringRef docString);
178 template <
typename Constra
intT>
180 createODSNativePDLLConstraintDecl(
const tblgen::Constraint &constraint,
181 SMRange loc, ast::Type type,
182 StringRef nativeType);
188 struct ParsedPatternMetadata {
189 std::optional<uint16_t> benefit;
190 bool hasBoundedRecursion =
false;
193 FailureOr<ast::Decl *> parseTopLevelDecl();
194 FailureOr<ast::NamedAttributeDecl *>
195 parseNamedAttributeDecl(std::optional<StringRef> parentOpName);
199 FailureOr<ast::VariableDecl *> parseArgumentDecl();
203 FailureOr<ast::VariableDecl *> parseResultDecl(
unsigned resultNum);
207 FailureOr<ast::UserConstraintDecl *>
208 parseUserConstraintDecl(
bool isInline =
false);
212 FailureOr<ast::UserConstraintDecl *> parseInlineUserConstraintDecl();
216 FailureOr<ast::UserConstraintDecl *> parseUserPDLLConstraintDecl(
217 const ast::Name &name,
bool isInline,
218 ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
219 ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
223 FailureOr<ast::UserRewriteDecl *> parseUserRewriteDecl(
bool isInline =
false);
227 FailureOr<ast::UserRewriteDecl *> parseInlineUserRewriteDecl();
231 FailureOr<ast::UserRewriteDecl *> parseUserPDLLRewriteDecl(
232 const ast::Name &name,
bool isInline,
233 ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
234 ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
239 template <
typename T,
typename ParseUserPDLLDeclFnT>
240 FailureOr<T *> parseUserConstraintOrRewriteDecl(
241 ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
242 StringRef anonymousNamePrefix,
bool isInline);
246 template <
typename T>
247 FailureOr<T *> parseUserNativeConstraintOrRewriteDecl(
248 const ast::Name &name,
bool isInline,
249 ArrayRef<ast::VariableDecl *> arguments,
250 ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
254 LogicalResult parseUserConstraintOrRewriteSignature(
255 SmallVectorImpl<ast::VariableDecl *> &arguments,
256 SmallVectorImpl<ast::VariableDecl *> &results,
257 ast::DeclScope *&argumentScope, ast::Type &resultType);
261 LogicalResult validateUserConstraintOrRewriteReturn(
262 StringRef declType, ast::CompoundStmt *body,
263 ArrayRef<ast::Stmt *>::iterator bodyIt,
264 ArrayRef<ast::Stmt *>::iterator bodyE,
265 ArrayRef<ast::VariableDecl *> results, ast::Type &resultType);
267 FailureOr<ast::CompoundStmt *>
268 parseLambdaBody(
function_ref<LogicalResult(ast::Stmt *&)> processStatementFn,
269 bool expectTerminalSemicolon =
true);
270 FailureOr<ast::CompoundStmt *> parsePatternLambdaBody();
271 FailureOr<ast::Decl *> parsePatternDecl();
272 LogicalResult parsePatternDeclMetadata(ParsedPatternMetadata &metadata);
276 LogicalResult checkDefineNamedDecl(
const ast::Name &name);
280 FailureOr<ast::VariableDecl *>
281 defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
283 ArrayRef<ast::ConstraintRef> constraints);
284 FailureOr<ast::VariableDecl *>
285 defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
286 ArrayRef<ast::ConstraintRef> constraints);
289 LogicalResult parseVariableDeclConstraintList(
290 SmallVectorImpl<ast::ConstraintRef> &constraints);
293 FailureOr<ast::Expr *> parseTypeConstraintExpr();
301 FailureOr<ast::ConstraintRef>
302 parseConstraint(std::optional<SMRange> &typeConstraint,
303 ArrayRef<ast::ConstraintRef> existingConstraints,
304 bool allowInlineTypeConstraints);
309 FailureOr<ast::ConstraintRef> parseArgOrResultConstraint();
314 FailureOr<ast::Expr *> parseExpr();
317 FailureOr<ast::Expr *> parseAttributeExpr();
318 FailureOr<ast::Expr *> parseCallExpr(ast::Expr *parentExpr,
319 bool isNegated =
false);
320 FailureOr<ast::Expr *> parseDeclRefExpr(StringRef name, SMRange loc);
321 FailureOr<ast::Expr *> parseIdentifierExpr();
322 FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr();
323 FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr();
324 FailureOr<ast::Expr *> parseMemberAccessExpr(ast::Expr *parentExpr);
325 FailureOr<ast::Expr *> parseNegatedExpr();
326 FailureOr<ast::OpNameDecl *> parseOperationName(
bool allowEmptyName =
false);
327 FailureOr<ast::OpNameDecl *> parseWrappedOperationName(
bool allowEmptyName);
328 FailureOr<ast::Expr *>
329 parseOperationExpr(OpResultTypeContext inputResultTypeContext =
330 OpResultTypeContext::Explicit);
331 FailureOr<ast::Expr *> parseTupleExpr();
332 FailureOr<ast::Expr *> parseTypeExpr();
333 FailureOr<ast::Expr *> parseUnderscoreExpr();
338 FailureOr<ast::Stmt *> parseStmt(
bool expectTerminalSemicolon =
true);
339 FailureOr<ast::CompoundStmt *> parseCompoundStmt();
340 FailureOr<ast::EraseStmt *> parseEraseStmt();
341 FailureOr<ast::LetStmt *> parseLetStmt();
342 FailureOr<ast::ReplaceStmt *> parseReplaceStmt();
343 FailureOr<ast::ReturnStmt *> parseReturnStmt();
344 FailureOr<ast::RewriteStmt *> parseRewriteStmt();
355 ast::CallableDecl *tryExtractCallableDecl(ast::Node *node);
359 FailureOr<ast::PatternDecl *>
360 createPatternDecl(SMRange loc,
const ast::Name *name,
361 const ParsedPatternMetadata &metadata,
362 ast::CompoundStmt *body);
367 createUserConstraintRewriteResultType(ArrayRef<ast::VariableDecl *> results);
370 template <
typename T>
371 FailureOr<T *> createUserPDLLConstraintOrRewriteDecl(
372 const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments,
373 ArrayRef<ast::VariableDecl *> results, ast::Type resultType,
374 ast::CompoundStmt *body);
378 FailureOr<ast::VariableDecl *>
379 createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer,
380 ArrayRef<ast::ConstraintRef> constraints);
384 FailureOr<ast::VariableDecl *>
385 createArgOrResultVariableDecl(StringRef name, SMRange loc,
386 const ast::ConstraintRef &constraint);
394 validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
395 ast::Type &inferredType);
400 LogicalResult validateVariableConstraint(
const ast::ConstraintRef &ref,
401 ast::Type &inferredType);
402 LogicalResult validateTypeConstraintExpr(
const ast::Expr *typeExpr);
403 LogicalResult validateTypeRangeConstraintExpr(
const ast::Expr *typeExpr);
408 FailureOr<ast::CallExpr *>
409 createCallExpr(SMRange loc, ast::Expr *parentExpr,
410 MutableArrayRef<ast::Expr *> arguments,
411 bool isNegated =
false);
412 FailureOr<ast::DeclRefExpr *> createDeclRefExpr(SMRange loc, ast::Decl *decl);
413 FailureOr<ast::DeclRefExpr *>
414 createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc,
415 ArrayRef<ast::ConstraintRef> constraints);
416 FailureOr<ast::MemberAccessExpr *>
417 createMemberAccessExpr(ast::Expr *parentExpr, StringRef name, SMRange loc);
421 FailureOr<ast::Type> validateMemberAccess(ast::Expr *parentExpr,
422 StringRef name, SMRange loc);
423 FailureOr<ast::OperationExpr *>
424 createOperationExpr(SMRange loc,
const ast::OpNameDecl *name,
425 OpResultTypeContext resultTypeContext,
426 SmallVectorImpl<ast::Expr *> &operands,
427 MutableArrayRef<ast::NamedAttributeDecl *> attributes,
428 SmallVectorImpl<ast::Expr *> &results);
430 validateOperationOperands(SMRange loc, std::optional<StringRef> name,
431 const ods::Operation *odsOp,
432 SmallVectorImpl<ast::Expr *> &operands);
433 LogicalResult validateOperationResults(SMRange loc,
434 std::optional<StringRef> name,
435 const ods::Operation *odsOp,
436 SmallVectorImpl<ast::Expr *> &results);
437 void checkOperationResultTypeInferrence(SMRange loc, StringRef name,
438 const ods::Operation *odsOp);
439 LogicalResult validateOperationOperandsOrResults(
440 StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
441 std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
442 ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
443 ast::RangeType rangeTy);
444 FailureOr<ast::TupleExpr *> createTupleExpr(SMRange loc,
445 ArrayRef<ast::Expr *> elements,
446 ArrayRef<StringRef> elementNames);
451 FailureOr<ast::EraseStmt *> createEraseStmt(SMRange loc, ast::Expr *rootOp);
452 FailureOr<ast::ReplaceStmt *>
453 createReplaceStmt(SMRange loc, ast::Expr *rootOp,
454 MutableArrayRef<ast::Expr *> replValues);
455 FailureOr<ast::RewriteStmt *>
456 createRewriteStmt(SMRange loc, ast::Expr *rootOp,
457 ast::CompoundStmt *rewriteBody);
467 LogicalResult codeCompleteMemberAccess(ast::Expr *parentExpr);
468 LogicalResult codeCompleteAttributeName(std::optional<StringRef> opName);
469 LogicalResult codeCompleteConstraintName(ast::Type inferredType,
470 bool allowInlineTypeConstraints);
471 LogicalResult codeCompleteDialectName();
472 LogicalResult codeCompleteOperationName(StringRef dialectName);
473 LogicalResult codeCompletePatternMetadata();
474 LogicalResult codeCompleteIncludeFilename(StringRef curPath);
476 void codeCompleteCallSignature(ast::Node *parent,
unsigned currentNumArgs);
477 void codeCompleteOperationOperandsSignature(std::optional<StringRef> opName,
478 unsigned currentNumOperands);
479 void codeCompleteOperationResultsSignature(std::optional<StringRef> opName,
480 unsigned currentNumResults);
489 if (curToken.isNot(kind))
496 void consumeToken() {
498 "shouldn't advance past EOF or errors");
499 curToken = lexer.lexToken();
506 assert(curToken.is(kind) &&
"consumed an unexpected token");
511 void resetToken(SMRange tokLoc) {
512 lexer.resetPointer(tokLoc.Start.getPointer());
513 curToken = lexer.lexToken();
518 LogicalResult parseToken(
Token::Kind kind,
const Twine &msg) {
519 if (curToken.getKind() != kind)
520 return emitError(curToken.getLoc(), msg);
524 LogicalResult
emitError(SMRange loc,
const Twine &msg) {
525 lexer.emitError(loc, msg);
528 LogicalResult
emitError(
const Twine &msg) {
529 return emitError(curToken.getLoc(), msg);
531 LogicalResult emitErrorAndNote(SMRange loc,
const Twine &msg, SMRange noteLoc,
533 lexer.emitErrorAndNote(loc, msg, noteLoc, note);
552 bool enableDocumentation;
555 ast::DeclScope *curDeclScope =
nullptr;
556 llvm::SpecificBumpPtrAllocator<ast::DeclScope> scopeAllocator;
559 ParserContext parserContext = ParserContext::Global;
562 ast::Type typeTy, valueTy;
563 ast::RangeType typeRangeTy, valueRangeTy;
567 unsigned anonymousDeclNameCounter = 0;
570 CodeCompleteContext *codeCompleteContext;
574FailureOr<ast::Module *> Parser::parseModule() {
575 SMLoc moduleLoc = curToken.getStartLoc();
579 SmallVector<ast::Decl *> decls;
580 if (
failed(parseModuleBody(decls)))
581 return popDeclScope(), failure();
587LogicalResult Parser::parseModuleBody(SmallVectorImpl<ast::Decl *> &decls) {
590 if (
failed(parseDirective(decls)))
595 FailureOr<ast::Decl *> decl = parseTopLevelDecl();
598 decls.push_back(*decl);
603ast::Expr *Parser::convertOpToValue(
const ast::Expr *opExpr) {
608LogicalResult Parser::convertExpressionTo(
609 ast::Expr *&expr, ast::Type type,
611 ast::Type exprType = expr->
getType();
612 if (exprType == type)
615 auto emitConvertError = [&]() -> ast::InFlightDiagnostic {
617 expr->
getLoc(), llvm::formatv(
"unable to convert expression of type "
618 "`{0}` to the expected type of "
626 if (
auto exprOpType = dyn_cast<ast::OperationType>(exprType))
627 return convertOpExpressionTo(expr, exprOpType, type, emitConvertError);
633 if ((exprType == valueTy || exprType == valueRangeTy) &&
634 (type == valueTy || type == valueRangeTy))
636 if ((exprType == typeTy || exprType == typeRangeTy) &&
637 (type == typeTy || type == typeRangeTy))
641 if (
auto exprTupleType = dyn_cast<ast::TupleType>(exprType))
642 return convertTupleExpressionTo(expr, exprTupleType, type, emitConvertError,
645 return emitConvertError();
648LogicalResult Parser::convertOpExpressionTo(
649 ast::Expr *&expr, ast::OperationType exprType, ast::Type type,
653 if (
auto opType = dyn_cast<ast::OperationType>(type)) {
654 if (opType.getName())
655 return emitErrorFn();
660 if (type == valueRangeTy) {
667 if (type == valueTy) {
671 if (odsOp->getResults().empty()) {
672 return emitErrorFn()->attachNote(
673 llvm::formatv(
"see the definition of `{0}`, which was defined "
679 unsigned numSingleResults = llvm::count_if(
680 odsOp->getResults(), [](
const ods::OperandOrResult &
result) {
681 return result.getVariableLengthKind() ==
682 ods::VariableLengthKind::Single;
684 if (numSingleResults > 1) {
685 return emitErrorFn()->attachNote(
686 llvm::formatv(
"see the definition of `{0}`, which was defined "
687 "with at least {1} results",
688 odsOp->getName(), numSingleResults),
697 return emitErrorFn();
700LogicalResult Parser::convertTupleExpressionTo(
701 ast::Expr *&expr, ast::TupleType exprType, ast::Type type,
705 if (
auto tupleType = dyn_cast<ast::TupleType>(type)) {
706 if (tupleType.size() != exprType.
size())
707 return emitErrorFn();
711 SmallVector<ast::Expr *> newExprs;
712 for (
unsigned i = 0, e = exprType.
size(); i < e; ++i) {
714 ctx, expr->
getLoc(), expr, llvm::to_string(i),
717 auto diagFn = [&](ast::Diagnostic &
diag) {
718 diag.attachNote(llvm::formatv(
"when converting element #{0} of `{1}`",
723 if (
failed(convertExpressionTo(newExprs.back(),
724 tupleType.getElementTypes()[i], diagFn)))
728 tupleType.getElementNames());
733 auto convertToRange = [&](ArrayRef<ast::Type> allowedElementTypes,
734 ast::RangeType resultTy) -> LogicalResult {
736 if (parserContext != ParserContext::Rewrite) {
737 return emitErrorFn()->attachNote(
"Tuple to Range conversion is currently "
738 "only allowed within a rewrite context");
743 if (!llvm::is_contained(allowedElementTypes, elementType))
744 return emitErrorFn();
748 SmallVector<ast::Expr *> newExprs;
749 for (
unsigned i = 0, e = exprType.
size(); i < e; ++i) {
751 ctx, expr->
getLoc(), expr, llvm::to_string(i),
757 if (type == valueRangeTy)
758 return convertToRange({valueTy, valueRangeTy}, valueRangeTy);
759 if (type == typeRangeTy)
760 return convertToRange({typeTy, typeRangeTy}, typeRangeTy);
762 return emitErrorFn();
769LogicalResult Parser::parseDirective(SmallVectorImpl<ast::Decl *> &decls) {
771 if (directive ==
"#include")
772 return parseInclude(decls);
774 return emitError(
"unknown directive `" + directive +
"`");
777LogicalResult Parser::parseInclude(SmallVectorImpl<ast::Decl *> &decls) {
778 SMRange loc = curToken.
getLoc();
786 if (!curToken.isString())
788 "expected string file name after `include` directive");
789 SMRange fileLoc = curToken.
getLoc();
791 StringRef filename = filenameStr;
796 if (filename.ends_with(
".pdll")) {
797 if (
failed(lexer.pushInclude(filename, fileLoc)))
799 "unable to open include file `" + filename +
"`");
805 LogicalResult
result = parseModuleBody(decls);
811 if (filename.ends_with(
".td"))
812 return parseTdInclude(filename, fileLoc, decls);
815 "expected include filename to end with `.pdll` or `.td`");
818LogicalResult Parser::parseTdInclude(StringRef filename, llvm::SMRange fileLoc,
819 SmallVectorImpl<ast::Decl *> &decls) {
823 std::string includedFile;
824 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> includeBuffer =
825 parserSrcMgr.OpenIncludeFile(filename.str(), includedFile);
827 return emitError(fileLoc,
"unable to open include file `" + filename +
"`");
830 llvm::SourceMgr tdSrcMgr;
831 tdSrcMgr.AddNewSourceBuffer(std::move(*includeBuffer), SMLoc());
832 tdSrcMgr.setIncludeDirs(parserSrcMgr.getIncludeDirs());
833 tdSrcMgr.setVirtualFileSystem(llvm::vfs::getRealFileSystem());
837 struct DiagHandlerContext {
841 } handlerContext{*
this, filename, fileLoc};
844 tdSrcMgr.setDiagHandler(
845 [](
const llvm::SMDiagnostic &
diag,
void *rawHandlerContext) {
846 auto *ctx =
reinterpret_cast<DiagHandlerContext *
>(rawHandlerContext);
847 (void)ctx->parser.emitError(
849 llvm::formatv(
"error while processing include file `{0}`: {1}",
850 ctx->filename,
diag.getMessage()));
855 llvm::RecordKeeper tdRecords;
856 if (llvm::TableGenParseFile(tdSrcMgr, tdRecords))
860 processTdIncludeRecords(tdRecords, decls);
865 parserSrcMgr.takeSourceBuffersFrom(tdSrcMgr, fileLoc.End);
869void Parser::processTdIncludeRecords(
const llvm::RecordKeeper &tdRecords,
870 SmallVectorImpl<ast::Decl *> &decls) {
872 auto getLengthKind = [](
const auto &value) {
873 if (value.isOptional())
874 return ods::VariableLengthKind::Optional;
875 return value.isVariadic() ? ods::VariableLengthKind::Variadic
876 : ods::VariableLengthKind::Single;
881 auto addTypeConstraint = [&](
const tblgen::NamedTypeConstraint &cst)
882 ->
const ods::TypeConstraint & {
884 cst.constraint.getUniqueDefName(),
885 processDoc(cst.constraint.getSummary()), cst.constraint.getCppType());
887 auto convertLocToRange = [&](llvm::SMLoc loc) -> llvm::SMRange {
888 return {loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)};
893 for (
const llvm::Record *def : tdRecords.getAllDerivedDefinitions(
"Op")) {
894 tblgen::Operator op(def);
897 bool supportsResultTypeInferrence =
898 op.getTrait(
"::mlir::InferTypeOpInterface::Trait");
901 op.getOperationName(), processDoc(op.getSummary()),
902 processAndFormatDoc(op.getDescription()), op.getQualCppClassName(),
903 supportsResultTypeInferrence, op.getLoc().front());
909 for (
const tblgen::NamedAttribute &attr : op.getAttributes()) {
910 odsOp->appendAttribute(attr.name, attr.attr.isOptional(),
912 attr.attr.getUniqueDefName(),
913 processDoc(attr.attr.getSummary()),
914 attr.attr.getStorageType()));
916 for (
const tblgen::NamedTypeConstraint &operand : op.getOperands()) {
917 odsOp->appendOperand(operand.name, getLengthKind(operand),
918 addTypeConstraint(operand));
920 for (
const tblgen::NamedTypeConstraint &
result : op.getResults()) {
922 addTypeConstraint(
result));
926 auto shouldBeSkipped = [
this](
const llvm::Record *def) {
927 return def->isAnonymous() || curDeclScope->
lookup(def->getName()) ||
928 def->isSubClassOf(
"DeclareInterfaceMethods");
932 for (
const llvm::Record *def : tdRecords.getAllDerivedDefinitions(
"Attr")) {
933 if (shouldBeSkipped(def))
936 tblgen::Attribute constraint(def);
937 decls.push_back(createODSNativePDLLConstraintDecl<ast::AttrConstraintDecl>(
938 constraint, convertLocToRange(def->getLoc().front()), attrTy,
939 constraint.getStorageType()));
942 for (
const llvm::Record *def : tdRecords.getAllDerivedDefinitions(
"Type")) {
943 if (shouldBeSkipped(def))
946 tblgen::TypeConstraint constraint(def);
947 decls.push_back(createODSNativePDLLConstraintDecl<ast::TypeConstraintDecl>(
948 constraint, convertLocToRange(def->getLoc().front()), typeTy,
949 constraint.getCppType()));
953 for (
const llvm::Record *def :
954 tdRecords.getAllDerivedDefinitions(
"OpInterface")) {
955 if (shouldBeSkipped(def))
958 SMRange loc = convertLocToRange(def->getLoc().front());
960 std::string cppClassName =
961 llvm::formatv(
"{0}::{1}", def->getValueAsString(
"cppNamespace"),
962 def->getValueAsString(
"cppInterfaceName"))
964 std::string codeBlock =
965 llvm::formatv(
"return ::mlir::success(llvm::isa<{0}>(self));",
970 processAndFormatDoc(def->getValueAsString(
"description"));
971 decls.push_back(createODSNativePDLLConstraintDecl<ast::OpConstraintDecl>(
972 def->getName(), codeBlock, loc, opTy, cppClassName, desc));
976template <
typename Constra
intT>
977ast::Decl *Parser::createODSNativePDLLConstraintDecl(
978 StringRef name, StringRef codeBlock, SMRange loc, ast::Type type,
979 StringRef nativeType, StringRef docString) {
981 ast::DeclScope *argScope = pushDeclScope();
984 nullptr, ast::ConstraintRef(ConstraintT::create(ctx, loc)));
985 argScope->
add(paramVar);
993 curDeclScope->
add(constraintDecl);
994 return constraintDecl;
997template <
typename Constra
intT>
999Parser::createODSNativePDLLConstraintDecl(
const tblgen::Constraint &constraint,
1000 SMRange loc, ast::Type type,
1001 StringRef nativeType) {
1003 tblgen::FmtContext fmtContext;
1012 std::string docString;
1013 if (enableDocumentation) {
1015 docString = processAndFormatDoc(
1020 return createODSNativePDLLConstraintDecl<ConstraintT>(
1029FailureOr<ast::Decl *> Parser::parseTopLevelDecl() {
1030 FailureOr<ast::Decl *> decl;
1033 decl = parseUserConstraintDecl();
1036 decl = parsePatternDecl();
1039 decl = parseUserRewriteDecl();
1042 return emitError(
"expected top-level declaration, such as a `Pattern`");
1048 if (
const ast::Name *name = (*decl)->getName()) {
1049 if (
failed(checkDefineNamedDecl(*name)))
1051 curDeclScope->
add(*decl);
1056FailureOr<ast::NamedAttributeDecl *>
1057Parser::parseNamedAttributeDecl(std::optional<StringRef> parentOpName) {
1060 return codeCompleteAttributeName(parentOpName);
1062 std::string attrNameStr;
1063 if (curToken.isString())
1068 return emitError(
"expected identifier or string attribute name");
1073 ast::Expr *attrValue =
nullptr;
1075 FailureOr<ast::Expr *> attrExpr = parseExpr();
1078 attrValue = *attrExpr;
1088FailureOr<ast::CompoundStmt *> Parser::parseLambdaBody(
1089 function_ref<LogicalResult(ast::Stmt *&)> processStatementFn,
1090 bool expectTerminalSemicolon) {
1094 SMLoc bodyStartLoc = curToken.getStartLoc();
1096 FailureOr<ast::Stmt *> singleStatement = parseStmt(expectTerminalSemicolon);
1097 bool failedToParse =
1098 failed(singleStatement) ||
failed(processStatementFn(*singleStatement));
1103 SMRange bodyLoc(bodyStartLoc, curToken.getStartLoc());
1107FailureOr<ast::VariableDecl *> Parser::parseArgumentDecl() {
1110 return emitError(
"expected identifier argument name");
1114 SMRange nameLoc = curToken.
getLoc();
1118 parseToken(
Token::colon,
"expected `:` before argument constraint")))
1121 FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1125 return createArgOrResultVariableDecl(name, nameLoc, *cst);
1128FailureOr<ast::VariableDecl *> Parser::parseResultDecl(
unsigned resultNum) {
1137 SMRange nameLoc = curToken.
getLoc();
1141 "expected `:` before result constraint")))
1144 FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1148 return createArgOrResultVariableDecl(name, nameLoc, *cst);
1154 FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1158 return createArgOrResultVariableDecl(
"", cst->referenceLoc, *cst);
1161FailureOr<ast::UserConstraintDecl *>
1162Parser::parseUserConstraintDecl(
bool isInline) {
1165 return parseUserConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1166 [&](
auto &&...args) {
1167 return this->parseUserPDLLConstraintDecl(args...);
1169 ParserContext::Constraint,
"constraint", isInline);
1172FailureOr<ast::UserConstraintDecl *> Parser::parseInlineUserConstraintDecl() {
1173 FailureOr<ast::UserConstraintDecl *> decl =
1174 parseUserConstraintDecl(
true);
1175 if (
failed(decl) ||
failed(checkDefineNamedDecl((*decl)->getName())))
1178 curDeclScope->
add(*decl);
1182FailureOr<ast::UserConstraintDecl *> Parser::parseUserPDLLConstraintDecl(
1183 const ast::Name &name,
bool isInline,
1184 ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
1185 ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1188 pushDeclScope(argumentScope);
1192 ast::CompoundStmt *body;
1194 FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1195 [&](ast::Stmt *&stmt) -> LogicalResult {
1196 ast::Expr *stmtExpr = dyn_cast<ast::Expr>(stmt);
1199 "expected `Constraint` lambda body to contain a "
1200 "single expression");
1210 FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1216 auto bodyIt = body->
begin(), bodyE = body->
end();
1217 for (; bodyIt != bodyE; ++bodyIt)
1218 if (isa<ast::ReturnStmt>(*bodyIt))
1220 if (
failed(validateUserConstraintOrRewriteReturn(
1221 "Constraint", body, bodyIt, bodyE, results, resultType)))
1226 return createUserPDLLConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1227 name, arguments, results, resultType, body);
1230FailureOr<ast::UserRewriteDecl *> Parser::parseUserRewriteDecl(
bool isInline) {
1233 return parseUserConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1234 [&](
auto &&...args) {
return this->parseUserPDLLRewriteDecl(args...); },
1235 ParserContext::Rewrite,
"rewrite", isInline);
1238FailureOr<ast::UserRewriteDecl *> Parser::parseInlineUserRewriteDecl() {
1239 FailureOr<ast::UserRewriteDecl *> decl =
1240 parseUserRewriteDecl(
true);
1241 if (
failed(decl) ||
failed(checkDefineNamedDecl((*decl)->getName())))
1244 curDeclScope->
add(*decl);
1248FailureOr<ast::UserRewriteDecl *> Parser::parseUserPDLLRewriteDecl(
1249 const ast::Name &name,
bool isInline,
1250 ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
1251 ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1254 curDeclScope = argumentScope;
1255 ast::CompoundStmt *body;
1257 FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1258 [&](ast::Stmt *&statement) -> LogicalResult {
1259 if (isa<ast::OpRewriteStmt>(statement))
1262 ast::Expr *statementExpr = dyn_cast<ast::Expr>(statement);
1263 if (!statementExpr) {
1266 "expected `Rewrite` lambda body to contain a single expression "
1267 "or an operation rewrite statement; such as `erase`, "
1268 "`replace`, or `rewrite`");
1279 FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1287 auto bodyIt = body->
begin(), bodyE = body->
end();
1288 for (; bodyIt != bodyE; ++bodyIt)
1289 if (isa<ast::ReturnStmt>(*bodyIt))
1291 if (
failed(validateUserConstraintOrRewriteReturn(
"Rewrite", body, bodyIt,
1292 bodyE, results, resultType)))
1294 return createUserPDLLConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1295 name, arguments, results, resultType, body);
1298template <
typename T,
typename ParseUserPDLLDeclFnT>
1299FailureOr<T *> Parser::parseUserConstraintOrRewriteDecl(
1300 ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
1301 StringRef anonymousNamePrefix,
bool isInline) {
1302 SMRange loc = curToken.
getLoc();
1304 llvm::SaveAndRestore saveCtx(parserContext, declContext);
1307 const ast::Name *name =
nullptr;
1312 return emitError(
"expected identifier name");
1316 std::string anonName =
1317 llvm::formatv(
"<anonymous_{0}_{1}>", anonymousNamePrefix,
1318 anonymousDeclNameCounter++)
1328 SmallVector<ast::VariableDecl *> arguments, results;
1329 ast::DeclScope *argumentScope;
1330 ast::Type resultType;
1331 if (
failed(parseUserConstraintOrRewriteSignature(arguments, results,
1332 argumentScope, resultType)))
1338 return parseUserPDLLFn(*name, isInline, arguments, argumentScope, results,
1342 return parseUserNativeConstraintOrRewriteDecl<T>(*name, isInline, arguments,
1343 results, resultType);
1346template <
typename T>
1347FailureOr<T *> Parser::parseUserNativeConstraintOrRewriteDecl(
1348 const ast::Name &name,
bool isInline,
1349 ArrayRef<ast::VariableDecl *> arguments,
1350 ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1352 std::string codeStrStorage;
1353 std::optional<StringRef> optCodeStr;
1354 if (curToken.isString()) {
1356 optCodeStr = codeStrStorage;
1358 }
else if (isInline) {
1360 "external declarations must be declared in global scope");
1365 "expected `;` after native declaration")))
1367 return T::createNative(ctx, name, arguments, results, optCodeStr, resultType);
1370LogicalResult Parser::parseUserConstraintOrRewriteSignature(
1371 SmallVectorImpl<ast::VariableDecl *> &arguments,
1372 SmallVectorImpl<ast::VariableDecl *> &results,
1373 ast::DeclScope *&argumentScope, ast::Type &resultType) {
1378 argumentScope = pushDeclScope();
1381 FailureOr<ast::VariableDecl *> argument = parseArgumentDecl();
1384 arguments.emplace_back(*argument);
1394 auto parseResultFn = [&]() -> LogicalResult {
1395 FailureOr<ast::VariableDecl *>
result = parseResultDecl(results.size());
1398 results.emplace_back(*
result);
1405 if (
failed(parseResultFn()))
1412 }
else if (
failed(parseResultFn())) {
1419 resultType = createUserConstraintRewriteResultType(results);
1422 if (results.size() == 1 && !results.front()->getName().getName().empty()) {
1424 results.front()->getLoc(),
1425 "cannot create a single-element tuple with an element label");
1430LogicalResult Parser::validateUserConstraintOrRewriteReturn(
1431 StringRef declType, ast::CompoundStmt *body,
1432 ArrayRef<ast::Stmt *>::iterator bodyIt,
1433 ArrayRef<ast::Stmt *>::iterator bodyE,
1434 ArrayRef<ast::VariableDecl *> results, ast::Type &resultType) {
1436 if (bodyIt != bodyE) {
1438 if (std::next(bodyIt) != bodyE) {
1440 (*std::next(bodyIt))->getLoc(),
1441 llvm::formatv(
"`return` terminated the `{0}` body, but found "
1442 "trailing statements afterwards",
1448 }
else if (!results.empty()) {
1451 llvm::formatv(
"missing return in a `{0}` expected to return `{1}`",
1452 declType, resultType));
1457FailureOr<ast::CompoundStmt *> Parser::parsePatternLambdaBody() {
1458 return parseLambdaBody([&](ast::Stmt *&statement) -> LogicalResult {
1459 if (isa<ast::OpRewriteStmt>(statement))
1463 "expected Pattern lambda body to contain a single operation "
1464 "rewrite statement, such as `erase`, `replace`, or `rewrite`");
1468FailureOr<ast::Decl *> Parser::parsePatternDecl() {
1469 SMRange loc = curToken.
getLoc();
1471 llvm::SaveAndRestore saveCtx(parserContext, ParserContext::PatternMatch);
1474 const ast::Name *name =
nullptr;
1481 ParsedPatternMetadata metadata;
1486 ast::CompoundStmt *body;
1490 FailureOr<ast::CompoundStmt *> bodyResult = parsePatternLambdaBody();
1496 return emitError(
"expected `{` or `=>` to start pattern body");
1497 FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1503 auto bodyIt = body->
begin(), bodyE = body->
end();
1504 for (; bodyIt != bodyE; ++bodyIt) {
1505 if (isa<ast::ReturnStmt>(*bodyIt)) {
1507 "`return` statements are only permitted within a "
1508 "`Constraint` or `Rewrite` body");
1511 if (isa<ast::OpRewriteStmt>(*bodyIt))
1514 if (bodyIt == bodyE) {
1516 "expected Pattern body to terminate with an operation "
1517 "rewrite statement, such as `erase`");
1519 if (std::next(bodyIt) != bodyE) {
1520 return emitError((*std::next(bodyIt))->getLoc(),
1521 "Pattern body was terminated by an operation "
1522 "rewrite statement, but found trailing statements");
1526 return createPatternDecl(loc, name, metadata, body);
1530Parser::parsePatternDeclMetadata(ParsedPatternMetadata &metadata) {
1531 std::optional<SMRange> benefitLoc;
1532 std::optional<SMRange> hasBoundedRecursionLoc;
1537 return codeCompletePatternMetadata();
1540 return emitError(
"expected pattern metadata identifier");
1542 SMRange metadataLoc = curToken.
getLoc();
1546 if (metadataStr ==
"benefit") {
1548 return emitErrorAndNote(metadataLoc,
1549 "pattern benefit has already been specified",
1550 *benefitLoc,
"see previous definition here");
1553 "expected `(` before pattern benefit")))
1556 uint16_t benefitValue = 0;
1558 return emitError(
"expected integral pattern benefit");
1559 if (curToken.
getSpelling().getAsInteger(10, benefitValue))
1561 "expected pattern benefit to fit within a 16-bit integer");
1564 metadata.benefit = benefitValue;
1565 benefitLoc = metadataLoc;
1568 parseToken(
Token::r_paren,
"expected `)` after pattern benefit")))
1574 if (metadataStr ==
"recursion") {
1575 if (hasBoundedRecursionLoc) {
1576 return emitErrorAndNote(
1578 "pattern recursion metadata has already been specified",
1579 *hasBoundedRecursionLoc,
"see previous definition here");
1581 metadata.hasBoundedRecursion =
true;
1582 hasBoundedRecursionLoc = metadataLoc;
1586 return emitError(metadataLoc,
"unknown pattern metadata");
1592FailureOr<ast::Expr *> Parser::parseTypeConstraintExpr() {
1595 FailureOr<ast::Expr *> typeExpr = parseExpr();
1598 "expected `>` after variable type constraint")))
1603LogicalResult Parser::checkDefineNamedDecl(
const ast::Name &name) {
1604 assert(curDeclScope &&
"defining decl outside of a decl scope");
1605 if (ast::Decl *lastDecl = curDeclScope->
lookup(name.
getName())) {
1606 return emitErrorAndNote(
1607 name.
getLoc(),
"`" + name.
getName() +
"` has already been defined",
1608 lastDecl->getName()->getLoc(),
"see previous definition here");
1613FailureOr<ast::VariableDecl *>
1614Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
1615 ast::Expr *initExpr,
1616 ArrayRef<ast::ConstraintRef> constraints) {
1617 assert(curDeclScope &&
"defining variable outside of decl scope");
1622 if (name.empty() || name ==
"_") {
1626 if (
failed(checkDefineNamedDecl(nameDecl)))
1631 curDeclScope->
add(varDecl);
1635FailureOr<ast::VariableDecl *>
1636Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
1637 ArrayRef<ast::ConstraintRef> constraints) {
1638 return defineVariableDecl(name, nameLoc, type,
nullptr,
1642LogicalResult Parser::parseVariableDeclConstraintList(
1643 SmallVectorImpl<ast::ConstraintRef> &constraints) {
1644 std::optional<SMRange> typeConstraint;
1645 auto parseSingleConstraint = [&] {
1646 FailureOr<ast::ConstraintRef> constraint = parseConstraint(
1647 typeConstraint, constraints,
true);
1650 constraints.push_back(*constraint);
1656 return parseSingleConstraint();
1659 if (
failed(parseSingleConstraint()))
1662 return parseToken(
Token::r_square,
"expected `]` after constraint list");
1665FailureOr<ast::ConstraintRef>
1666Parser::parseConstraint(std::optional<SMRange> &typeConstraint,
1667 ArrayRef<ast::ConstraintRef> existingConstraints,
1668 bool allowInlineTypeConstraints) {
1669 auto parseTypeConstraint = [&](ast::Expr *&typeExpr) -> LogicalResult {
1670 if (!allowInlineTypeConstraints) {
1673 "inline `Attr`, `Value`, and `ValueRange` type constraints are not "
1674 "permitted on arguments or results");
1677 return emitErrorAndNote(
1679 "the type of this variable has already been constrained",
1680 *typeConstraint,
"see previous constraint location here");
1681 FailureOr<ast::Expr *> constraintExpr = parseTypeConstraintExpr();
1682 if (
failed(constraintExpr))
1684 typeExpr = *constraintExpr;
1685 typeConstraint = typeExpr->getLoc();
1689 SMRange loc = curToken.
getLoc();
1695 ast::Expr *typeExpr =
nullptr;
1698 return ast::ConstraintRef(
1706 FailureOr<ast::OpNameDecl *> opName =
1707 parseWrappedOperationName(
true);
1725 ast::Expr *typeExpr =
nullptr;
1729 return ast::ConstraintRef(
1736 ast::Expr *typeExpr =
nullptr;
1740 return ast::ConstraintRef(
1746 FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1749 return ast::ConstraintRef(*decl, loc);
1752 StringRef constraintName = curToken.
getSpelling();
1756 ast::Decl *cstDecl = curDeclScope->
lookup<ast::Decl>(constraintName);
1758 return emitError(loc,
"unknown reference to constraint `" +
1759 constraintName +
"`");
1763 if (
auto *cst = dyn_cast<ast::ConstraintDecl>(cstDecl))
1764 return ast::ConstraintRef(cst, loc);
1766 return emitErrorAndNote(
1767 loc,
"invalid reference to non-constraint", cstDecl->
getLoc(),
1768 "see the definition of `" + constraintName +
"` here");
1773 ast::Type inferredType;
1774 if (
failed(validateVariableConstraints(existingConstraints, inferredType)))
1777 return codeCompleteConstraintName(inferredType, allowInlineTypeConstraints);
1782 return emitError(loc,
"expected identifier constraint");
1785FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() {
1786 std::optional<SMRange> typeConstraint;
1787 return parseConstraint(typeConstraint, {},
1795FailureOr<ast::Expr *> Parser::parseExpr() {
1797 return parseUnderscoreExpr();
1800 FailureOr<ast::Expr *> lhsExpr;
1803 lhsExpr = parseAttributeExpr();
1806 lhsExpr = parseInlineConstraintLambdaExpr();
1809 lhsExpr = parseNegatedExpr();
1812 lhsExpr = parseIdentifierExpr();
1815 lhsExpr = parseOperationExpr();
1818 lhsExpr = parseInlineRewriteLambdaExpr();
1821 lhsExpr = parseTypeExpr();
1824 lhsExpr = parseTupleExpr();
1827 return emitError(
"expected expression");
1836 lhsExpr = parseMemberAccessExpr(*lhsExpr);
1839 lhsExpr = parseCallExpr(*lhsExpr);
1849FailureOr<ast::Expr *> Parser::parseAttributeExpr() {
1850 SMRange loc = curToken.
getLoc();
1857 return parseIdentifierExpr();
1860 if (!curToken.isString())
1861 return emitError(
"expected string literal containing MLIR attribute");
1867 parseToken(
Token::greater,
"expected `>` after attribute literal")))
1872FailureOr<ast::Expr *> Parser::parseCallExpr(ast::Expr *parentExpr,
1877 SmallVector<ast::Expr *> arguments;
1882 codeCompleteCallSignature(parentExpr, arguments.size());
1886 FailureOr<ast::Expr *> argument = parseExpr();
1889 arguments.push_back(*argument);
1897 return createCallExpr(loc, parentExpr, arguments, isNegated);
1900FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) {
1901 ast::Decl *decl = curDeclScope->
lookup(name);
1903 return emitError(loc,
"undefined reference to `" + name +
"`");
1905 return createDeclRefExpr(loc, decl);
1908FailureOr<ast::Expr *> Parser::parseIdentifierExpr() {
1910 SMRange nameLoc = curToken.
getLoc();
1916 SmallVector<ast::ConstraintRef> constraints;
1917 if (
failed(parseVariableDeclConstraintList(constraints)))
1920 if (
failed(validateVariableConstraints(constraints, type)))
1922 return createInlineVariableExpr(type, name, nameLoc, constraints);
1925 return parseDeclRefExpr(name, nameLoc);
1928FailureOr<ast::Expr *> Parser::parseInlineConstraintLambdaExpr() {
1929 FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1937FailureOr<ast::Expr *> Parser::parseInlineRewriteLambdaExpr() {
1938 FailureOr<ast::UserRewriteDecl *> decl = parseInlineUserRewriteDecl();
1946FailureOr<ast::Expr *> Parser::parseMemberAccessExpr(ast::Expr *parentExpr) {
1947 SMRange dotLoc = curToken.
getLoc();
1952 return codeCompleteMemberAccess(parentExpr);
1955 Token memberNameTok = curToken;
1958 return emitError(dotLoc,
"expected identifier or numeric member name");
1959 StringRef memberName = memberNameTok.
getSpelling();
1963 return createMemberAccessExpr(parentExpr, memberName, loc);
1966FailureOr<ast::Expr *> Parser::parseNegatedExpr() {
1970 return emitError(
"expected native constraint");
1971 FailureOr<ast::Expr *> identifierExpr = parseIdentifierExpr();
1972 if (
failed(identifierExpr))
1975 return emitError(
"expected `(` after function name");
1976 return parseCallExpr(*identifierExpr,
true);
1979FailureOr<ast::OpNameDecl *> Parser::parseOperationName(
bool allowEmptyName) {
1980 SMRange loc = curToken.
getLoc();
1984 return codeCompleteDialectName();
1990 return emitError(
"expected dialect namespace");
1996 if (
failed(parseToken(
Token::dot,
"expected `.` after dialect namespace")))
2001 return codeCompleteOperationName(name);
2004 return emitError(
"expected operation name after dialect namespace");
2006 name = StringRef(name.data(), name.size() + 1);
2008 name = StringRef(name.data(), name.size() + curToken.
getSpelling().size());
2016FailureOr<ast::OpNameDecl *>
2017Parser::parseWrappedOperationName(
bool allowEmptyName) {
2021 FailureOr<ast::OpNameDecl *> opNameDecl = parseOperationName(allowEmptyName);
2030FailureOr<ast::Expr *>
2031Parser::parseOperationExpr(OpResultTypeContext inputResultTypeContext) {
2032 SMRange loc = curToken.
getLoc();
2039 return parseIdentifierExpr();
2045 bool allowEmptyName = parserContext != ParserContext::Rewrite;
2046 FailureOr<ast::OpNameDecl *> opNameDecl =
2047 parseWrappedOperationName(allowEmptyName);
2050 std::optional<StringRef> opName = (*opNameDecl)->getName();
2054 auto createImplicitRangeVar = [&](ast::ConstraintDecl *cst, ast::Type type) {
2055 FailureOr<ast::VariableDecl *> rangeVar =
2056 defineVariableDecl(
"_", loc, type, ast::ConstraintRef(cst, loc));
2057 assert(succeeded(rangeVar) &&
"expected range variable to be valid");
2062 SmallVector<ast::Expr *> operands;
2068 if (parserContext != ParserContext::Rewrite) {
2069 operands.push_back(createImplicitRangeVar(
2077 codeCompleteOperationOperandsSignature(opName, operands.size());
2081 FailureOr<ast::Expr *> operand = parseExpr();
2084 operands.push_back(*operand);
2088 "expected `)` after operation operand list")))
2093 SmallVector<ast::NamedAttributeDecl *> attributes;
2096 FailureOr<ast::NamedAttributeDecl *> decl =
2097 parseNamedAttributeDecl(opName);
2100 attributes.emplace_back(*decl);
2104 "expected `}` after operation attribute list")))
2109 SmallVector<ast::Expr *> resultTypes;
2110 OpResultTypeContext resultTypeContext = inputResultTypeContext;
2115 "expected `(` before operation result type list")))
2123 resultTypeContext = OpResultTypeContext::Explicit;
2130 codeCompleteOperationResultsSignature(opName, resultTypes.size());
2134 FailureOr<ast::Expr *> resultTypeExpr = parseExpr();
2135 if (
failed(resultTypeExpr))
2137 resultTypes.push_back(*resultTypeExpr);
2141 "expected `)` after operation result type list")))
2144 }
else if (parserContext != ParserContext::Rewrite) {
2149 resultTypes.push_back(createImplicitRangeVar(
2151 }
else if (resultTypeContext == OpResultTypeContext::Explicit) {
2154 resultTypeContext = OpResultTypeContext::Interface;
2157 return createOperationExpr(loc, *opNameDecl, resultTypeContext, operands,
2158 attributes, resultTypes);
2161FailureOr<ast::Expr *> Parser::parseTupleExpr() {
2162 SMRange loc = curToken.
getLoc();
2166 SmallVector<StringRef> elementNames;
2167 SmallVector<ast::Expr *> elements;
2171 StringRef elementName;
2173 Token elementNameTok = curToken;
2181 auto elementNameIt =
2182 usedNames.try_emplace(elementName, elementNameTok.
getLoc());
2183 if (!elementNameIt.second) {
2184 return emitErrorAndNote(
2186 llvm::formatv(
"duplicate tuple element label `{0}`",
2188 elementNameIt.first->getSecond(),
2189 "see previous label use here");
2194 resetToken(elementNameTok.
getLoc());
2197 elementNames.push_back(elementName);
2200 FailureOr<ast::Expr *> element = parseExpr();
2203 elements.push_back(*element);
2208 parseToken(
Token::r_paren,
"expected `)` after tuple element list")))
2210 return createTupleExpr(loc, elements, elementNames);
2213FailureOr<ast::Expr *> Parser::parseTypeExpr() {
2214 SMRange loc = curToken.
getLoc();
2221 return parseIdentifierExpr();
2224 if (!curToken.isString())
2225 return emitError(
"expected string literal containing MLIR type");
2235FailureOr<ast::Expr *> Parser::parseUnderscoreExpr() {
2237 SMRange nameLoc = curToken.
getLoc();
2245 SmallVector<ast::ConstraintRef> constraints;
2246 if (
failed(parseVariableDeclConstraintList(constraints)))
2250 if (
failed(validateVariableConstraints(constraints, type)))
2252 return createInlineVariableExpr(type, name, nameLoc, constraints);
2259FailureOr<ast::Stmt *> Parser::parseStmt(
bool expectTerminalSemicolon) {
2260 FailureOr<ast::Stmt *> stmt;
2263 stmt = parseEraseStmt();
2266 stmt = parseLetStmt();
2269 stmt = parseReplaceStmt();
2272 stmt = parseReturnStmt();
2275 stmt = parseRewriteStmt();
2282 (expectTerminalSemicolon &&
2288FailureOr<ast::CompoundStmt *> Parser::parseCompoundStmt() {
2289 SMLoc startLoc = curToken.getStartLoc();
2294 SmallVector<ast::Stmt *> statements;
2296 FailureOr<ast::Stmt *> statement = parseStmt();
2298 return popDeclScope(), failure();
2299 statements.push_back(*statement);
2304 SMRange location(startLoc, curToken.
getEndLoc());
2310FailureOr<ast::EraseStmt *> Parser::parseEraseStmt() {
2311 if (parserContext == ParserContext::Constraint)
2312 return emitError(
"`erase` cannot be used within a Constraint");
2313 SMRange loc = curToken.
getLoc();
2317 FailureOr<ast::Expr *> rootOp = parseExpr();
2321 return createEraseStmt(loc, *rootOp);
2324FailureOr<ast::LetStmt *> Parser::parseLetStmt() {
2325 SMRange loc = curToken.
getLoc();
2329 SMRange varLoc = curToken.
getLoc();
2334 "`_` may only be used to define \"inline\" variables");
2337 "expected identifier after `let` to name a new variable");
2343 SmallVector<ast::ConstraintRef> constraints;
2345 failed(parseVariableDeclConstraintList(constraints)))
2349 ast::Expr *initializer =
nullptr;
2351 FailureOr<ast::Expr *> initOrFailure = parseExpr();
2352 if (
failed(initOrFailure))
2354 initializer = *initOrFailure;
2358 for (ast::ConstraintRef constraint : constraints) {
2361 .Case<ast::AttrConstraintDecl, ast::ValueConstraintDecl,
2362 ast::ValueRangeConstraintDecl>([&](
const auto *cst) {
2363 if (cst->getTypeExpr()) {
2365 constraint.referenceLoc,
2366 "type constraints are not permitted on variables with "
2377 FailureOr<ast::VariableDecl *> varDecl =
2378 createVariableDecl(varName, varLoc, initializer, constraints);
2384FailureOr<ast::ReplaceStmt *> Parser::parseReplaceStmt() {
2385 if (parserContext == ParserContext::Constraint)
2386 return emitError(
"`replace` cannot be used within a Constraint");
2387 SMRange loc = curToken.
getLoc();
2391 FailureOr<ast::Expr *> rootOp = parseExpr();
2396 parseToken(
Token::kw_with,
"expected `with` after root operation")))
2400 llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite);
2403 SmallVector<ast::Expr *> replValues;
2407 loc,
"expected at least one replacement value, consider using "
2408 "`erase` if no replacement values are desired");
2412 FailureOr<ast::Expr *> replExpr = parseExpr();
2415 replValues.emplace_back(*replExpr);
2419 "expected `)` after replacement values")))
2424 FailureOr<ast::Expr *> replExpr;
2426 replExpr = parseOperationExpr(OpResultTypeContext::Replacement);
2428 replExpr = parseExpr();
2431 replValues.emplace_back(*replExpr);
2434 return createReplaceStmt(loc, *rootOp, replValues);
2437FailureOr<ast::ReturnStmt *> Parser::parseReturnStmt() {
2438 SMRange loc = curToken.
getLoc();
2442 FailureOr<ast::Expr *> resultExpr = parseExpr();
2449FailureOr<ast::RewriteStmt *> Parser::parseRewriteStmt() {
2450 if (parserContext == ParserContext::Constraint)
2451 return emitError(
"`rewrite` cannot be used within a Constraint");
2452 SMRange loc = curToken.
getLoc();
2456 FailureOr<ast::Expr *> rootOp = parseExpr();
2464 return emitError(
"expected `{` to start rewrite body");
2467 llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite);
2469 FailureOr<ast::CompoundStmt *> rewriteBody = parseCompoundStmt();
2474 for (
const ast::Stmt *stmt : (*rewriteBody)->getChildren()) {
2475 if (isa<ast::ReturnStmt>(stmt)) {
2477 "`return` statements are only permitted within a "
2478 "`Constraint` or `Rewrite` body");
2482 return createRewriteStmt(loc, *rootOp, *rewriteBody);
2493ast::CallableDecl *Parser::tryExtractCallableDecl(ast::Node *node) {
2495 if (
auto *init = dyn_cast<ast::DeclRefExpr>(node))
2496 node = init->getDecl();
2497 return dyn_cast<ast::CallableDecl>(node);
2500FailureOr<ast::PatternDecl *>
2501Parser::createPatternDecl(SMRange loc,
const ast::Name *name,
2502 const ParsedPatternMetadata &metadata,
2503 ast::CompoundStmt *body) {
2505 metadata.hasBoundedRecursion, body);
2508ast::Type Parser::createUserConstraintRewriteResultType(
2509 ArrayRef<ast::VariableDecl *> results) {
2511 if (results.size() == 1)
2512 return results[0]->getType();
2516 auto resultTypes = llvm::map_range(
2517 results, [&](
const auto *
result) {
return result->getType(); });
2518 auto resultNames = llvm::map_range(
2519 results, [&](
const auto *
result) {
return result->getName().getName(); });
2521 llvm::to_vector(resultNames));
2524template <
typename T>
2525FailureOr<T *> Parser::createUserPDLLConstraintOrRewriteDecl(
2526 const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments,
2527 ArrayRef<ast::VariableDecl *> results, ast::Type resultType,
2528 ast::CompoundStmt *body) {
2530 if (
auto *retStmt = dyn_cast<ast::ReturnStmt>(body->
getChildren().back())) {
2531 ast::Expr *resultExpr = retStmt->getResultExpr();
2536 if (results.empty())
2537 resultType = resultExpr->
getType();
2538 else if (
failed(convertExpressionTo(resultExpr, resultType)))
2541 retStmt->setResultExpr(resultExpr);
2544 return T::createPDLL(ctx, name, arguments, results, body, resultType);
2547FailureOr<ast::VariableDecl *>
2548Parser::createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer,
2549 ArrayRef<ast::ConstraintRef> constraints) {
2553 if (
failed(validateVariableConstraints(constraints, type)))
2560 type = initializer->
getType();
2563 else if (
failed(convertExpressionTo(initializer, type)))
2569 return emitErrorAndNote(
2570 loc,
"unable to infer type for variable `" + name +
"`", loc,
2571 "the type of a variable must be inferable from the constraint "
2572 "list or the initializer");
2576 if (isa<ast::ConstraintType, ast::RewriteType>(type)) {
2578 loc, llvm::formatv(
"unable to define variable of `{0}` type", type));
2582 FailureOr<ast::VariableDecl *> varDecl =
2583 defineVariableDecl(name, loc, type, initializer, constraints);
2590FailureOr<ast::VariableDecl *>
2591Parser::createArgOrResultVariableDecl(StringRef name, SMRange loc,
2592 const ast::ConstraintRef &constraint) {
2594 if (
failed(validateVariableConstraint(constraint, argType)))
2596 return defineVariableDecl(name, loc, argType, constraint);
2600Parser::validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
2601 ast::Type &inferredType) {
2602 for (
const ast::ConstraintRef &ref : constraints)
2603 if (
failed(validateVariableConstraint(ref, inferredType)))
2608LogicalResult Parser::validateVariableConstraint(
const ast::ConstraintRef &ref,
2609 ast::Type &inferredType) {
2610 ast::Type constraintType;
2611 if (
const auto *cst = dyn_cast<ast::AttrConstraintDecl>(ref.
constraint)) {
2612 if (
const ast::Expr *typeExpr = cst->getTypeExpr()) {
2613 if (
failed(validateTypeConstraintExpr(typeExpr)))
2617 }
else if (
const auto *cst =
2618 dyn_cast<ast::OpConstraintDecl>(ref.
constraint)) {
2621 }
else if (isa<ast::TypeConstraintDecl>(ref.
constraint)) {
2622 constraintType = typeTy;
2623 }
else if (isa<ast::TypeRangeConstraintDecl>(ref.
constraint)) {
2624 constraintType = typeRangeTy;
2625 }
else if (
const auto *cst =
2626 dyn_cast<ast::ValueConstraintDecl>(ref.
constraint)) {
2627 if (
const ast::Expr *typeExpr = cst->getTypeExpr()) {
2628 if (
failed(validateTypeConstraintExpr(typeExpr)))
2631 constraintType = valueTy;
2632 }
else if (
const auto *cst =
2633 dyn_cast<ast::ValueRangeConstraintDecl>(ref.
constraint)) {
2634 if (
const ast::Expr *typeExpr = cst->getTypeExpr()) {
2635 if (
failed(validateTypeRangeConstraintExpr(typeExpr)))
2638 constraintType = valueRangeTy;
2639 }
else if (
const auto *cst =
2640 dyn_cast<ast::UserConstraintDecl>(ref.
constraint)) {
2641 ArrayRef<ast::VariableDecl *> inputs = cst->getInputs();
2642 if (inputs.size() != 1) {
2644 "`Constraint`s applied via a variable constraint "
2645 "list must take a single input, but got " +
2646 Twine(inputs.size()),
2648 "see definition of constraint here");
2650 constraintType = inputs.front()->getType();
2652 llvm_unreachable(
"unknown constraint type");
2657 if (!inferredType) {
2658 inferredType = constraintType;
2659 }
else if (ast::Type mergedTy = inferredType.
refineWith(constraintType)) {
2660 inferredType = mergedTy;
2663 llvm::formatv(
"constraint type `{0}` is incompatible "
2664 "with the previously inferred type `{1}`",
2665 constraintType, inferredType));
2670LogicalResult Parser::validateTypeConstraintExpr(
const ast::Expr *typeExpr) {
2671 ast::Type typeExprType = typeExpr->
getType();
2672 if (typeExprType != typeTy) {
2674 "expected expression of `Type` in type constraint");
2680Parser::validateTypeRangeConstraintExpr(
const ast::Expr *typeExpr) {
2681 ast::Type typeExprType = typeExpr->
getType();
2682 if (typeExprType != typeRangeTy) {
2684 "expected expression of `TypeRange` in type constraint");
2693FailureOr<ast::CallExpr *>
2694Parser::createCallExpr(SMRange loc, ast::Expr *parentExpr,
2695 MutableArrayRef<ast::Expr *> arguments,
bool isNegated) {
2696 ast::Type parentType = parentExpr->
getType();
2698 ast::CallableDecl *callableDecl = tryExtractCallableDecl(parentExpr);
2699 if (!callableDecl) {
2701 llvm::formatv(
"expected a reference to a callable "
2702 "`Constraint` or `Rewrite`, but got: `{0}`",
2705 if (parserContext == ParserContext::Rewrite) {
2706 if (isa<ast::UserConstraintDecl>(callableDecl))
2708 loc,
"unable to invoke `Constraint` within a rewrite section");
2710 return emitError(loc,
"unable to negate a Rewrite");
2712 if (isa<ast::UserRewriteDecl>(callableDecl))
2714 "unable to invoke `Rewrite` within a match section");
2715 if (isNegated && cast<ast::UserConstraintDecl>(callableDecl)->getBody())
2716 return emitError(loc,
"unable to negate non native constraints");
2721 ArrayRef<ast::VariableDecl *> callArgs = callableDecl->
getInputs();
2722 if (callArgs.size() != arguments.size()) {
2723 return emitErrorAndNote(
2725 llvm::formatv(
"invalid number of arguments for {0} call; expected "
2730 llvm::formatv(
"see the definition of {0} here",
2735 auto attachDiagFn = [&](ast::Diagnostic &
diag) {
2736 diag.attachNote(llvm::formatv(
"see the definition of `{0}` here",
2740 for (
auto it : llvm::zip(callArgs, arguments)) {
2741 if (
failed(convertExpressionTo(std::get<1>(it), std::get<0>(it)->
getType(),
2750FailureOr<ast::DeclRefExpr *> Parser::createDeclRefExpr(SMRange loc,
2754 if (isa<ast::ConstraintDecl>(decl))
2756 else if (isa<ast::UserRewriteDecl>(decl))
2758 else if (
auto *varDecl = dyn_cast<ast::VariableDecl>(decl))
2759 declType = varDecl->getType();
2761 return emitError(loc,
"invalid reference to `" +
2767FailureOr<ast::DeclRefExpr *>
2768Parser::createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc,
2769 ArrayRef<ast::ConstraintRef> constraints) {
2770 FailureOr<ast::VariableDecl *> decl =
2771 defineVariableDecl(name, loc, type, constraints);
2777FailureOr<ast::MemberAccessExpr *>
2778Parser::createMemberAccessExpr(ast::Expr *parentExpr, StringRef name,
2781 FailureOr<ast::Type> memberType = validateMemberAccess(parentExpr, name, loc);
2788FailureOr<ast::Type> Parser::validateMemberAccess(ast::Expr *parentExpr,
2789 StringRef name, SMRange loc) {
2790 ast::Type parentType = parentExpr->
getType();
2791 if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType)) {
2793 return valueRangeTy;
2796 if (
const ods::Operation *odsOp = opType.getODSOperation()) {
2797 auto results = odsOp->getResults();
2801 if (llvm::isDigit(name[0]) && !name.getAsInteger(10, index) &&
2802 index < results.size()) {
2803 return results[index].isVariadic() ? valueRangeTy : valueTy;
2807 const auto *it = llvm::find_if(results, [&](
const auto &
result) {
2808 return result.getName() == name;
2810 if (it != results.end())
2811 return it->isVariadic() ? valueRangeTy : valueTy;
2812 }
else if (llvm::isDigit(name[0])) {
2814 if (name.getAsInteger(10, index))
2815 return emitError(loc,
"result index is too large");
2821 }
else if (
auto tupleType = dyn_cast<ast::TupleType>(parentType)) {
2824 if (llvm::isDigit(name[0]) && !name.getAsInteger(10, index) &&
2825 index < tupleType.size()) {
2826 return tupleType.getElementTypes()[index];
2830 auto elementNames = tupleType.getElementNames();
2831 const auto *it = llvm::find(elementNames, name);
2832 if (it != elementNames.end())
2833 return tupleType.getElementTypes()[it - elementNames.begin()];
2837 llvm::formatv(
"invalid member access `{0}` on expression of type `{1}`",
2841FailureOr<ast::OperationExpr *> Parser::createOperationExpr(
2842 SMRange loc,
const ast::OpNameDecl *name,
2843 OpResultTypeContext resultTypeContext,
2844 SmallVectorImpl<ast::Expr *> &operands,
2845 MutableArrayRef<ast::NamedAttributeDecl *> attributes,
2846 SmallVectorImpl<ast::Expr *> &results) {
2847 std::optional<StringRef> opNameRef = name->
getName();
2848 const ods::Operation *odsOp = lookupODSOperation(opNameRef);
2851 if (
failed(validateOperationOperands(loc, opNameRef, odsOp, operands)))
2855 for (ast::NamedAttributeDecl *attr : attributes) {
2857 ast::Type attrType = attr->getValue()->getType();
2858 if (!isa<ast::AttributeType>(attrType)) {
2860 attr->getValue()->getLoc(),
2861 llvm::formatv(
"expected `Attr` expression, but got `{0}`", attrType));
2866 (resultTypeContext == OpResultTypeContext::Explicit || results.empty()) &&
2867 "unexpected inferrence when results were explicitly specified");
2871 if (resultTypeContext == OpResultTypeContext::Explicit) {
2872 if (
failed(validateOperationResults(loc, opNameRef, odsOp, results)))
2876 }
else if (resultTypeContext == OpResultTypeContext::Interface) {
2878 "expected valid operation name when inferring operation results");
2879 checkOperationResultTypeInferrence(loc, *opNameRef, odsOp);
2887Parser::validateOperationOperands(SMRange loc, std::optional<StringRef> name,
2888 const ods::Operation *odsOp,
2889 SmallVectorImpl<ast::Expr *> &operands) {
2890 return validateOperationOperandsOrResults(
2891 "operand", loc, odsOp ? odsOp->
getLoc() : std::optional<SMRange>(), name,
2893 odsOp ? odsOp->
getOperands() : ArrayRef<pdll::ods::OperandOrResult>(),
2894 valueTy, valueRangeTy);
2898Parser::validateOperationResults(SMRange loc, std::optional<StringRef> name,
2899 const ods::Operation *odsOp,
2900 SmallVectorImpl<ast::Expr *> &results) {
2901 return validateOperationOperandsOrResults(
2902 "result", loc, odsOp ? odsOp->
getLoc() : std::optional<SMRange>(), name,
2904 odsOp ? odsOp->
getResults() : ArrayRef<pdll::ods::OperandOrResult>(),
2905 typeTy, typeRangeTy);
2908void Parser::checkOperationResultTypeInferrence(SMRange loc, StringRef opName,
2909 const ods::Operation *odsOp) {
2919 "operation result types are marked to be inferred, but "
2920 "`{0}` is unknown. Ensure that `{0}` supports zero "
2921 "results or implements `InferTypeOpInterface`. Include "
2922 "the ODS definition of this operation to remove this warning.",
2931 bool requiresInferrence =
2933 return !result.isVariableLength();
2938 llvm::formatv(
"operation result types are marked to be inferred, but "
2939 "`{0}` does not provide an implementation of "
2940 "`InferTypeOpInterface`. Ensure that `{0}` attaches "
2941 "`InferTypeOpInterface` at runtime, or add support to "
2942 "the ODS definition to remove this warning.",
2944 diag->
attachNote(llvm::formatv(
"see the definition of `{0}` here", opName),
2950LogicalResult Parser::validateOperationOperandsOrResults(
2951 StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
2952 std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
2953 ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
2954 ast::RangeType rangeTy) {
2956 if (values.size() == 1) {
2957 if (
failed(convertExpressionTo(values[0], rangeTy)))
2965 auto emitSizeMismatchError = [&] {
2966 return emitErrorAndNote(
2968 llvm::formatv(
"invalid number of {0} groups for `{1}`; expected "
2970 groupName, *name, odsValues.size(), values.size()),
2971 *odsOpLoc, llvm::formatv(
"see the definition of `{0}` here", *name));
2975 if (values.empty()) {
2977 if (odsValues.empty())
2982 unsigned numVariadic = 0;
2983 for (
const auto &odsValue : odsValues) {
2984 if (!odsValue.isVariableLength())
2985 return emitSizeMismatchError();
2991 if (parserContext != ParserContext::Rewrite)
2998 if (numVariadic == 1)
3003 for (
unsigned i = 0, e = odsValues.size(); i < e; ++i) {
3012 if (odsValues.size() != values.size())
3013 return emitSizeMismatchError();
3015 auto diagFn = [&](ast::Diagnostic &
diag) {
3016 diag.attachNote(llvm::formatv(
"see the definition of `{0}` here", *name),
3019 for (
unsigned i = 0, e = values.size(); i < e; ++i) {
3020 ast::Type expectedType = odsValues[i].isVariadic() ? rangeTy : singleTy;
3021 if (
failed(convertExpressionTo(values[i], expectedType, diagFn)))
3029 for (ast::Expr *&valueExpr : values) {
3030 ast::Type valueExprType = valueExpr->getType();
3033 if (valueExprType == rangeTy || valueExprType == singleTy)
3039 if (singleTy == valueTy) {
3040 if (isa<ast::OperationType>(valueExprType)) {
3041 valueExpr = convertOpToValue(valueExpr);
3047 if (succeeded(convertExpressionTo(valueExpr, rangeTy)))
3051 valueExpr->getLoc(),
3053 "expected `{0}` or `{1}` convertible expression, but got `{2}`",
3054 singleTy, rangeTy, valueExprType));
3059FailureOr<ast::TupleExpr *>
3060Parser::createTupleExpr(SMRange loc, ArrayRef<ast::Expr *> elements,
3061 ArrayRef<StringRef> elementNames) {
3062 for (
const ast::Expr *element : elements) {
3063 ast::Type eleTy = element->getType();
3064 if (isa<ast::ConstraintType, ast::RewriteType, ast::TupleType>(eleTy)) {
3067 llvm::formatv(
"unable to build a tuple with `{0}` element", eleTy));
3077FailureOr<ast::EraseStmt *> Parser::createEraseStmt(SMRange loc,
3078 ast::Expr *rootOp) {
3080 ast::Type rootType = rootOp->
getType();
3081 if (!isa<ast::OperationType>(rootType))
3087FailureOr<ast::ReplaceStmt *>
3088Parser::createReplaceStmt(SMRange loc, ast::Expr *rootOp,
3089 MutableArrayRef<ast::Expr *> replValues) {
3091 ast::Type rootType = rootOp->
getType();
3092 if (!isa<ast::OperationType>(rootType)) {
3095 llvm::formatv(
"expected `Op` expression, but got `{0}`", rootType));
3100 bool shouldConvertOpToValues = replValues.size() > 1;
3101 for (ast::Expr *&replExpr : replValues) {
3102 ast::Type replType = replExpr->getType();
3105 if (isa<ast::OperationType>(replType)) {
3106 if (shouldConvertOpToValues)
3107 replExpr = convertOpToValue(replExpr);
3111 if (replType != valueTy && replType != valueRangeTy) {
3113 llvm::formatv(
"expected `Op`, `Value` or `ValueRange` "
3114 "expression, but got `{0}`",
3122FailureOr<ast::RewriteStmt *>
3123Parser::createRewriteStmt(SMRange loc, ast::Expr *rootOp,
3124 ast::CompoundStmt *rewriteBody) {
3126 ast::Type rootType = rootOp->
getType();
3127 if (!isa<ast::OperationType>(rootType)) {
3130 llvm::formatv(
"expected `Op` expression, but got `{0}`", rootType));
3140LogicalResult Parser::codeCompleteMemberAccess(ast::Expr *parentExpr) {
3141 ast::Type parentType = parentExpr->
getType();
3142 if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType))
3144 else if (ast::TupleType tupleType = dyn_cast<ast::TupleType>(parentType))
3150Parser::codeCompleteAttributeName(std::optional<StringRef> opName) {
3157Parser::codeCompleteConstraintName(ast::Type inferredType,
3158 bool allowInlineTypeConstraints) {
3160 inferredType, allowInlineTypeConstraints, curDeclScope);
3164LogicalResult Parser::codeCompleteDialectName() {
3169LogicalResult Parser::codeCompleteOperationName(StringRef dialectName) {
3174LogicalResult Parser::codeCompletePatternMetadata() {
3179LogicalResult Parser::codeCompleteIncludeFilename(StringRef curPath) {
3184void Parser::codeCompleteCallSignature(ast::Node *parent,
3185 unsigned currentNumArgs) {
3186 ast::CallableDecl *callableDecl = tryExtractCallableDecl(parent);
3193void Parser::codeCompleteOperationOperandsSignature(
3194 std::optional<StringRef> opName,
unsigned currentNumOperands) {
3196 opName, currentNumOperands);
3199void Parser::codeCompleteOperationResultsSignature(
3200 std::optional<StringRef> opName,
unsigned currentNumResults) {
3209FailureOr<ast::Module *>
3211 bool enableDocumentation,
3213 Parser parser(ctx, sourceMgr, enableDocumentation, codeCompleteContext);
3214 return parser.parseModule();
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static std::string diag(const llvm::Value &value)
const llvm::SourceMgr & getSourceMgr()
bool isKeyword() const
Return true if this is one of the keyword token kinds (e.g. kw_if).
std::string getStringValue() const
Given a token containing a string literal, return its value, including removing the quote characters ...
bool isAny(Kind k1, Kind k2) const
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)
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)
Type getResultType() const
Return the result type of this decl.
StringRef getCallableType() const
Return the callable type of this decl.
ArrayRef< VariableDecl * > getInputs() const
Return the inputs of this decl.
ArrayRef< Stmt * >::iterator end() const
MutableArrayRef< Stmt * > getChildren()
Return the children of this compound statement.
ArrayRef< Stmt * >::iterator begin() const
static CompoundStmt * create(Context &ctx, SMRange location, ArrayRef< Stmt * > children)
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.
Decl * lookup(StringRef name)
Lookup a decl with the given name starting from this scope.
void add(Decl *decl)
Add a new decl to the scope.
DeclScope * getParentScope()
Return the parent scope of this scope, or nullptr if there is no parent.
void setDocComment(Context &ctx, StringRef comment)
Set the documentation comment for this decl.
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.
Diagnostic & attachNote(const Twine &msg, std::optional< SMRange > noteLoc=std::nullopt)
Attach a note to this 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)
static NamedAttributeDecl * create(Context &ctx, const Name &name, Expr *value)
SMRange getLoc() const
Return the location of this node.
static OpConstraintDecl * create(Context &ctx, SMRange loc, const OpNameDecl *nameDecl=nullptr)
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)
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.
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.
static ValueConstraintDecl * create(Context &ctx, SMRange loc, Expr *typeExpr)
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)
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.
ArrayRef< OperandOrResult > getOperands() const
Returns the operands of this operation.
SMRange getLoc() const
Return the source location 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.
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
FmtContext & withSelf(Twine subst)
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::FormatFunctor< Ts >(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.
llvm::TypeSwitch< T, ResultT > TypeSwitch
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
llvm::function_ref< Fn > function_ref
const ConstraintDecl * constraint
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)