111d26bd1SRiver Riddle //===- Parser.cpp ---------------------------------------------------------===// 211d26bd1SRiver Riddle // 311d26bd1SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 411d26bd1SRiver Riddle // See https://llvm.org/LICENSE.txt for license information. 511d26bd1SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 611d26bd1SRiver Riddle // 711d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 811d26bd1SRiver Riddle 911d26bd1SRiver Riddle #include "mlir/Tools/PDLL/Parser/Parser.h" 1011d26bd1SRiver Riddle #include "Lexer.h" 11bf352e0bSRiver Riddle #include "mlir/Support/IndentedOstream.h" 1281f2f4dfSRiver Riddle #include "mlir/TableGen/Argument.h" 1381f2f4dfSRiver Riddle #include "mlir/TableGen/Attribute.h" 1481f2f4dfSRiver Riddle #include "mlir/TableGen/Constraint.h" 1581f2f4dfSRiver Riddle #include "mlir/TableGen/Format.h" 1681f2f4dfSRiver Riddle #include "mlir/TableGen/Operator.h" 1711d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Context.h" 1811d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Diagnostic.h" 1911d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Nodes.h" 2011d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Types.h" 2181f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Constraint.h" 2281f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Context.h" 2381f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Operation.h" 24008de486SRiver Riddle #include "mlir/Tools/PDLL/Parser/CodeComplete.h" 25f62a57a3SRiver Riddle #include "llvm/ADT/StringExtras.h" 2611d26bd1SRiver Riddle #include "llvm/ADT/TypeSwitch.h" 2711d26bd1SRiver Riddle #include "llvm/Support/FormatVariadic.h" 2881f2f4dfSRiver Riddle #include "llvm/Support/ManagedStatic.h" 2911d26bd1SRiver Riddle #include "llvm/Support/SaveAndRestore.h" 30f62a57a3SRiver Riddle #include "llvm/Support/ScopedPrinter.h" 3181f2f4dfSRiver Riddle #include "llvm/TableGen/Error.h" 3281f2f4dfSRiver Riddle #include "llvm/TableGen/Parser.h" 33a1fe1f5fSKazu Hirata #include <optional> 342545cac5SMehdi Amini #include <string> 3511d26bd1SRiver Riddle 3611d26bd1SRiver Riddle using namespace mlir; 3711d26bd1SRiver Riddle using namespace mlir::pdll; 3811d26bd1SRiver Riddle 3911d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 4011d26bd1SRiver Riddle // Parser 4111d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 4211d26bd1SRiver Riddle 4311d26bd1SRiver Riddle namespace { 4411d26bd1SRiver Riddle class Parser { 4511d26bd1SRiver Riddle public: 46008de486SRiver Riddle Parser(ast::Context &ctx, llvm::SourceMgr &sourceMgr, 47bf352e0bSRiver Riddle bool enableDocumentation, CodeCompleteContext *codeCompleteContext) 48008de486SRiver Riddle : ctx(ctx), lexer(sourceMgr, ctx.getDiagEngine(), codeCompleteContext), 49bf352e0bSRiver Riddle curToken(lexer.lexToken()), enableDocumentation(enableDocumentation), 509e57210aSRiver Riddle typeTy(ast::TypeType::get(ctx)), valueTy(ast::ValueType::get(ctx)), 5181f2f4dfSRiver Riddle typeRangeTy(ast::TypeRangeType::get(ctx)), 529e57210aSRiver Riddle valueRangeTy(ast::ValueRangeType::get(ctx)), 53008de486SRiver Riddle attrTy(ast::AttributeType::get(ctx)), 54008de486SRiver Riddle codeCompleteContext(codeCompleteContext) {} 5511d26bd1SRiver Riddle 5611d26bd1SRiver Riddle /// Try to parse a new module. Returns nullptr in the case of failure. 5711d26bd1SRiver Riddle FailureOr<ast::Module *> parseModule(); 5811d26bd1SRiver Riddle 5911d26bd1SRiver Riddle private: 6011d26bd1SRiver Riddle /// The current context of the parser. It allows for the parser to know a bit 6111d26bd1SRiver Riddle /// about the construct it is nested within during parsing. This is used 6211d26bd1SRiver Riddle /// specifically to provide additional verification during parsing, e.g. to 6311d26bd1SRiver Riddle /// prevent using rewrites within a match context, matcher constraints within 6411d26bd1SRiver Riddle /// a rewrite section, etc. 6511d26bd1SRiver Riddle enum class ParserContext { 6611d26bd1SRiver Riddle /// The parser is in the global context. 6711d26bd1SRiver Riddle Global, 68faf42264SRiver Riddle /// The parser is currently within a Constraint, which disallows all types 69faf42264SRiver Riddle /// of rewrites (e.g. `erase`, `replace`, calls to Rewrites, etc.). 70faf42264SRiver Riddle Constraint, 7111d26bd1SRiver Riddle /// The parser is currently within the matcher portion of a Pattern, which 7211d26bd1SRiver Riddle /// is allows a terminal operation rewrite statement but no other rewrite 7311d26bd1SRiver Riddle /// transformations. 7411d26bd1SRiver Riddle PatternMatch, 7512eebb8eSRiver Riddle /// The parser is currently within a Rewrite, which disallows calls to 7612eebb8eSRiver Riddle /// constraints, requires operation expressions to have names, etc. 7712eebb8eSRiver Riddle Rewrite, 7811d26bd1SRiver Riddle }; 7911d26bd1SRiver Riddle 8091b8d96fSRiver Riddle /// The current specification context of an operations result type. This 8191b8d96fSRiver Riddle /// indicates how the result types of an operation may be inferred. 8291b8d96fSRiver Riddle enum class OpResultTypeContext { 8391b8d96fSRiver Riddle /// The result types of the operation are not known to be inferred. 8491b8d96fSRiver Riddle Explicit, 8591b8d96fSRiver Riddle /// The result types of the operation are inferred from the root input of a 8691b8d96fSRiver Riddle /// `replace` statement. 8791b8d96fSRiver Riddle Replacement, 8891b8d96fSRiver Riddle /// The result types of the operation are inferred by using the 8991b8d96fSRiver Riddle /// `InferTypeOpInterface` interface provided by the operation. 9091b8d96fSRiver Riddle Interface, 9191b8d96fSRiver Riddle }; 9291b8d96fSRiver Riddle 9311d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 9411d26bd1SRiver Riddle // Parsing 9511d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 9611d26bd1SRiver Riddle 9711d26bd1SRiver Riddle /// Push a new decl scope onto the lexer. 9811d26bd1SRiver Riddle ast::DeclScope *pushDeclScope() { 9911d26bd1SRiver Riddle ast::DeclScope *newScope = 10011d26bd1SRiver Riddle new (scopeAllocator.Allocate()) ast::DeclScope(curDeclScope); 10111d26bd1SRiver Riddle return (curDeclScope = newScope); 10211d26bd1SRiver Riddle } 10311d26bd1SRiver Riddle void pushDeclScope(ast::DeclScope *scope) { curDeclScope = scope; } 10411d26bd1SRiver Riddle 10511d26bd1SRiver Riddle /// Pop the last decl scope from the lexer. 10611d26bd1SRiver Riddle void popDeclScope() { curDeclScope = curDeclScope->getParentScope(); } 10711d26bd1SRiver Riddle 10811d26bd1SRiver Riddle /// Parse the body of an AST module. 10981f2f4dfSRiver Riddle LogicalResult parseModuleBody(SmallVectorImpl<ast::Decl *> &decls); 11011d26bd1SRiver Riddle 11111d26bd1SRiver Riddle /// Try to convert the given expression to `type`. Returns failure and emits 11211d26bd1SRiver Riddle /// an error if a conversion is not viable. On failure, `noteAttachFn` is 11311d26bd1SRiver Riddle /// invoked to attach notes to the emitted error diagnostic. On success, 11411d26bd1SRiver Riddle /// `expr` is updated to the expression used to convert to `type`. 11511d26bd1SRiver Riddle LogicalResult convertExpressionTo( 11611d26bd1SRiver Riddle ast::Expr *&expr, ast::Type type, 11711d26bd1SRiver Riddle function_ref<void(ast::Diagnostic &diag)> noteAttachFn = {}); 1189e57210aSRiver Riddle LogicalResult 1199e57210aSRiver Riddle convertOpExpressionTo(ast::Expr *&expr, ast::OperationType exprType, 1209e57210aSRiver Riddle ast::Type type, 1219e57210aSRiver Riddle function_ref<ast::InFlightDiagnostic()> emitErrorFn); 1229e57210aSRiver Riddle LogicalResult convertTupleExpressionTo( 1239e57210aSRiver Riddle ast::Expr *&expr, ast::TupleType exprType, ast::Type type, 1249e57210aSRiver Riddle function_ref<ast::InFlightDiagnostic()> emitErrorFn, 1259e57210aSRiver Riddle function_ref<void(ast::Diagnostic &diag)> noteAttachFn); 12611d26bd1SRiver Riddle 12702670c3fSRiver Riddle /// Given an operation expression, convert it to a Value or ValueRange 12802670c3fSRiver Riddle /// typed expression. 12902670c3fSRiver Riddle ast::Expr *convertOpToValue(const ast::Expr *opExpr); 13002670c3fSRiver Riddle 13181f2f4dfSRiver Riddle /// Lookup ODS information for the given operation, returns nullptr if no 13281f2f4dfSRiver Riddle /// information is found. 1330a81ace0SKazu Hirata const ods::Operation *lookupODSOperation(std::optional<StringRef> opName) { 13481f2f4dfSRiver Riddle return opName ? ctx.getODSContext().lookupOperation(*opName) : nullptr; 13581f2f4dfSRiver Riddle } 13681f2f4dfSRiver Riddle 137bf352e0bSRiver Riddle /// Process the given documentation string, or return an empty string if 138bf352e0bSRiver Riddle /// documentation isn't enabled. 139bf352e0bSRiver Riddle StringRef processDoc(StringRef doc) { 140bf352e0bSRiver Riddle return enableDocumentation ? doc : StringRef(); 141bf352e0bSRiver Riddle } 142bf352e0bSRiver Riddle 143bf352e0bSRiver Riddle /// Process the given documentation string and format it, or return an empty 144bf352e0bSRiver Riddle /// string if documentation isn't enabled. 145bf352e0bSRiver Riddle std::string processAndFormatDoc(const Twine &doc) { 146bf352e0bSRiver Riddle if (!enableDocumentation) 147bf352e0bSRiver Riddle return ""; 148bf352e0bSRiver Riddle std::string docStr; 149bf352e0bSRiver Riddle { 150bf352e0bSRiver Riddle llvm::raw_string_ostream docOS(docStr); 151bf352e0bSRiver Riddle raw_indented_ostream(docOS).printReindented( 152*095b41c6SJOE1994 StringRef(docStr).rtrim(" \t")); 153bf352e0bSRiver Riddle } 154bf352e0bSRiver Riddle return docStr; 155bf352e0bSRiver Riddle } 156bf352e0bSRiver Riddle 15711d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 15811d26bd1SRiver Riddle // Directives 15911d26bd1SRiver Riddle 16081f2f4dfSRiver Riddle LogicalResult parseDirective(SmallVectorImpl<ast::Decl *> &decls); 16181f2f4dfSRiver Riddle LogicalResult parseInclude(SmallVectorImpl<ast::Decl *> &decls); 16281f2f4dfSRiver Riddle LogicalResult parseTdInclude(StringRef filename, SMRange fileLoc, 16381f2f4dfSRiver Riddle SmallVectorImpl<ast::Decl *> &decls); 16481f2f4dfSRiver Riddle 16581f2f4dfSRiver Riddle /// Process the records of a parsed tablegen include file. 166b60c6cbcSRahul Joshi void processTdIncludeRecords(const llvm::RecordKeeper &tdRecords, 16781f2f4dfSRiver Riddle SmallVectorImpl<ast::Decl *> &decls); 16881f2f4dfSRiver Riddle 16981f2f4dfSRiver Riddle /// Create a user defined native constraint for a constraint imported from 17081f2f4dfSRiver Riddle /// ODS. 17181f2f4dfSRiver Riddle template <typename ConstraintT> 172bf352e0bSRiver Riddle ast::Decl * 173bf352e0bSRiver Riddle createODSNativePDLLConstraintDecl(StringRef name, StringRef codeBlock, 174bf352e0bSRiver Riddle SMRange loc, ast::Type type, 175bf352e0bSRiver Riddle StringRef nativeType, StringRef docString); 17681f2f4dfSRiver Riddle template <typename ConstraintT> 17781f2f4dfSRiver Riddle ast::Decl * 17881f2f4dfSRiver Riddle createODSNativePDLLConstraintDecl(const tblgen::Constraint &constraint, 1791c2edb02SRiver Riddle SMRange loc, ast::Type type, 1801c2edb02SRiver Riddle StringRef nativeType); 18111d26bd1SRiver Riddle 18211d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 18311d26bd1SRiver Riddle // Decls 18411d26bd1SRiver Riddle 185322691abSRiver Riddle /// This structure contains the set of pattern metadata that may be parsed. 186322691abSRiver Riddle struct ParsedPatternMetadata { 1870a81ace0SKazu Hirata std::optional<uint16_t> benefit; 188322691abSRiver Riddle bool hasBoundedRecursion = false; 189322691abSRiver Riddle }; 190322691abSRiver Riddle 19111d26bd1SRiver Riddle FailureOr<ast::Decl *> parseTopLevelDecl(); 192008de486SRiver Riddle FailureOr<ast::NamedAttributeDecl *> 1930a81ace0SKazu Hirata parseNamedAttributeDecl(std::optional<StringRef> parentOpName); 194faf42264SRiver Riddle 195faf42264SRiver Riddle /// Parse an argument variable as part of the signature of a 196faf42264SRiver Riddle /// UserConstraintDecl or UserRewriteDecl. 197faf42264SRiver Riddle FailureOr<ast::VariableDecl *> parseArgumentDecl(); 198faf42264SRiver Riddle 199faf42264SRiver Riddle /// Parse a result variable as part of the signature of a UserConstraintDecl 200faf42264SRiver Riddle /// or UserRewriteDecl. 201faf42264SRiver Riddle FailureOr<ast::VariableDecl *> parseResultDecl(unsigned resultNum); 202faf42264SRiver Riddle 203faf42264SRiver Riddle /// Parse a UserConstraintDecl. `isInline` signals if the constraint is being 204faf42264SRiver Riddle /// defined in a non-global context. 205faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> 206faf42264SRiver Riddle parseUserConstraintDecl(bool isInline = false); 207faf42264SRiver Riddle 208faf42264SRiver Riddle /// Parse an inline UserConstraintDecl. An inline decl is one defined in a 209faf42264SRiver Riddle /// non-global context, such as within a Pattern/Constraint/etc. 210faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> parseInlineUserConstraintDecl(); 211faf42264SRiver Riddle 212faf42264SRiver Riddle /// Parse a PDLL (i.e. non-native) UserRewriteDecl whose body is defined using 213faf42264SRiver Riddle /// PDLL constructs. 214faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> parseUserPDLLConstraintDecl( 215faf42264SRiver Riddle const ast::Name &name, bool isInline, 216faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope, 217faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType); 218faf42264SRiver Riddle 219faf42264SRiver Riddle /// Parse a parseUserRewriteDecl. `isInline` signals if the rewrite is being 220faf42264SRiver Riddle /// defined in a non-global context. 221faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> parseUserRewriteDecl(bool isInline = false); 222faf42264SRiver Riddle 223faf42264SRiver Riddle /// Parse an inline UserRewriteDecl. An inline decl is one defined in a 224faf42264SRiver Riddle /// non-global context, such as within a Pattern/Rewrite/etc. 225faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> parseInlineUserRewriteDecl(); 226faf42264SRiver Riddle 227faf42264SRiver Riddle /// Parse a PDLL (i.e. non-native) UserRewriteDecl whose body is defined using 228faf42264SRiver Riddle /// PDLL constructs. 229faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> parseUserPDLLRewriteDecl( 230faf42264SRiver Riddle const ast::Name &name, bool isInline, 231faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope, 232faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType); 233faf42264SRiver Riddle 234faf42264SRiver Riddle /// Parse either a UserConstraintDecl or UserRewriteDecl. These decls have 235faf42264SRiver Riddle /// effectively the same syntax, and only differ on slight semantics (given 236faf42264SRiver Riddle /// the different parsing contexts). 237faf42264SRiver Riddle template <typename T, typename ParseUserPDLLDeclFnT> 238faf42264SRiver Riddle FailureOr<T *> parseUserConstraintOrRewriteDecl( 239faf42264SRiver Riddle ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext, 240faf42264SRiver Riddle StringRef anonymousNamePrefix, bool isInline); 241faf42264SRiver Riddle 242faf42264SRiver Riddle /// Parse a native (i.e. non-PDLL) UserConstraintDecl or UserRewriteDecl. 243faf42264SRiver Riddle /// These decls have effectively the same syntax. 244faf42264SRiver Riddle template <typename T> 245faf42264SRiver Riddle FailureOr<T *> parseUserNativeConstraintOrRewriteDecl( 246faf42264SRiver Riddle const ast::Name &name, bool isInline, 247faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> arguments, 248faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType); 249faf42264SRiver Riddle 250faf42264SRiver Riddle /// Parse the functional signature (i.e. the arguments and results) of a 251faf42264SRiver Riddle /// UserConstraintDecl or UserRewriteDecl. 252faf42264SRiver Riddle LogicalResult parseUserConstraintOrRewriteSignature( 253faf42264SRiver Riddle SmallVectorImpl<ast::VariableDecl *> &arguments, 254faf42264SRiver Riddle SmallVectorImpl<ast::VariableDecl *> &results, 255faf42264SRiver Riddle ast::DeclScope *&argumentScope, ast::Type &resultType); 256faf42264SRiver Riddle 257faf42264SRiver Riddle /// Validate the return (which if present is specified by bodyIt) of a 258faf42264SRiver Riddle /// UserConstraintDecl or UserRewriteDecl. 259faf42264SRiver Riddle LogicalResult validateUserConstraintOrRewriteReturn( 260faf42264SRiver Riddle StringRef declType, ast::CompoundStmt *body, 261faf42264SRiver Riddle ArrayRef<ast::Stmt *>::iterator bodyIt, 262faf42264SRiver Riddle ArrayRef<ast::Stmt *>::iterator bodyE, 263faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type &resultType); 264faf42264SRiver Riddle 2653d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> 2663d8b9060SRiver Riddle parseLambdaBody(function_ref<LogicalResult(ast::Stmt *&)> processStatementFn, 2673d8b9060SRiver Riddle bool expectTerminalSemicolon = true); 2683d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> parsePatternLambdaBody(); 26911d26bd1SRiver Riddle FailureOr<ast::Decl *> parsePatternDecl(); 270322691abSRiver Riddle LogicalResult parsePatternDeclMetadata(ParsedPatternMetadata &metadata); 27111d26bd1SRiver Riddle 27211d26bd1SRiver Riddle /// Check to see if a decl has already been defined with the given name, if 27311d26bd1SRiver Riddle /// one has emit and error and return failure. Returns success otherwise. 27411d26bd1SRiver Riddle LogicalResult checkDefineNamedDecl(const ast::Name &name); 27511d26bd1SRiver Riddle 27611d26bd1SRiver Riddle /// Try to define a variable decl with the given components, returns the 27711d26bd1SRiver Riddle /// variable on success. 27811d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> 2796842ec42SRiver Riddle defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type, 28011d26bd1SRiver Riddle ast::Expr *initExpr, 28111d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints); 28211d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> 2836842ec42SRiver Riddle defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type, 28411d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints); 28511d26bd1SRiver Riddle 28611d26bd1SRiver Riddle /// Parse the constraint reference list for a variable decl. 28711d26bd1SRiver Riddle LogicalResult parseVariableDeclConstraintList( 28811d26bd1SRiver Riddle SmallVectorImpl<ast::ConstraintRef> &constraints); 28911d26bd1SRiver Riddle 29011d26bd1SRiver Riddle /// Parse the expression used within a type constraint, e.g. Attr<type-expr>. 29111d26bd1SRiver Riddle FailureOr<ast::Expr *> parseTypeConstraintExpr(); 29211d26bd1SRiver Riddle 29311d26bd1SRiver Riddle /// Try to parse a single reference to a constraint. `typeConstraint` is the 29411d26bd1SRiver Riddle /// location of a previously parsed type constraint for the entity that will 29511d26bd1SRiver Riddle /// be constrained by the parsed constraint. `existingConstraints` are any 29611d26bd1SRiver Riddle /// existing constraints that have already been parsed for the same entity 297faf42264SRiver Riddle /// that will be constrained by this constraint. `allowInlineTypeConstraints` 298faf42264SRiver Riddle /// allows the use of inline Type constraints, e.g. `Value<valueType: Type>`. 29911d26bd1SRiver Riddle FailureOr<ast::ConstraintRef> 3000a81ace0SKazu Hirata parseConstraint(std::optional<SMRange> &typeConstraint, 301faf42264SRiver Riddle ArrayRef<ast::ConstraintRef> existingConstraints, 302b6ec1de7SRiver Riddle bool allowInlineTypeConstraints); 303faf42264SRiver Riddle 304faf42264SRiver Riddle /// Try to parse the constraint for a UserConstraintDecl/UserRewriteDecl 305faf42264SRiver Riddle /// argument or result variable. The constraints for these variables do not 306faf42264SRiver Riddle /// allow inline type constraints, and only permit a single constraint. 307faf42264SRiver Riddle FailureOr<ast::ConstraintRef> parseArgOrResultConstraint(); 30811d26bd1SRiver Riddle 30911d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 31011d26bd1SRiver Riddle // Exprs 31111d26bd1SRiver Riddle 31211d26bd1SRiver Riddle FailureOr<ast::Expr *> parseExpr(); 31311d26bd1SRiver Riddle 31411d26bd1SRiver Riddle /// Identifier expressions. 315d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> parseAttributeExpr(); 316930916c7SMogball FailureOr<ast::Expr *> parseCallExpr(ast::Expr *parentExpr, 317930916c7SMogball bool isNegated = false); 3186842ec42SRiver Riddle FailureOr<ast::Expr *> parseDeclRefExpr(StringRef name, SMRange loc); 31911d26bd1SRiver Riddle FailureOr<ast::Expr *> parseIdentifierExpr(); 320faf42264SRiver Riddle FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr(); 321faf42264SRiver Riddle FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr(); 32211d26bd1SRiver Riddle FailureOr<ast::Expr *> parseMemberAccessExpr(ast::Expr *parentExpr); 323930916c7SMogball FailureOr<ast::Expr *> parseNegatedExpr(); 32412eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> parseOperationName(bool allowEmptyName = false); 32512eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> parseWrappedOperationName(bool allowEmptyName); 32691b8d96fSRiver Riddle FailureOr<ast::Expr *> 32791b8d96fSRiver Riddle parseOperationExpr(OpResultTypeContext inputResultTypeContext = 32891b8d96fSRiver Riddle OpResultTypeContext::Explicit); 329f62a57a3SRiver Riddle FailureOr<ast::Expr *> parseTupleExpr(); 330d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> parseTypeExpr(); 33111d26bd1SRiver Riddle FailureOr<ast::Expr *> parseUnderscoreExpr(); 33211d26bd1SRiver Riddle 33311d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 33411d26bd1SRiver Riddle // Stmts 33511d26bd1SRiver Riddle 33611d26bd1SRiver Riddle FailureOr<ast::Stmt *> parseStmt(bool expectTerminalSemicolon = true); 33711d26bd1SRiver Riddle FailureOr<ast::CompoundStmt *> parseCompoundStmt(); 33811d26bd1SRiver Riddle FailureOr<ast::EraseStmt *> parseEraseStmt(); 33911d26bd1SRiver Riddle FailureOr<ast::LetStmt *> parseLetStmt(); 34012eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *> parseReplaceStmt(); 341faf42264SRiver Riddle FailureOr<ast::ReturnStmt *> parseReturnStmt(); 3423ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *> parseRewriteStmt(); 34311d26bd1SRiver Riddle 34411d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 34511d26bd1SRiver Riddle // Creation+Analysis 34611d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 34711d26bd1SRiver Riddle 34811d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 34911d26bd1SRiver Riddle // Decls 35011d26bd1SRiver Riddle 351faf42264SRiver Riddle /// Try to extract a callable from the given AST node. Returns nullptr on 352faf42264SRiver Riddle /// failure. 353faf42264SRiver Riddle ast::CallableDecl *tryExtractCallableDecl(ast::Node *node); 354faf42264SRiver Riddle 35511d26bd1SRiver Riddle /// Try to create a pattern decl with the given components, returning the 35611d26bd1SRiver Riddle /// Pattern on success. 357322691abSRiver Riddle FailureOr<ast::PatternDecl *> 3586842ec42SRiver Riddle createPatternDecl(SMRange loc, const ast::Name *name, 359322691abSRiver Riddle const ParsedPatternMetadata &metadata, 36011d26bd1SRiver Riddle ast::CompoundStmt *body); 36111d26bd1SRiver Riddle 362faf42264SRiver Riddle /// Build the result type for a UserConstraintDecl/UserRewriteDecl given a set 363faf42264SRiver Riddle /// of results, defined as part of the signature. 364faf42264SRiver Riddle ast::Type 365faf42264SRiver Riddle createUserConstraintRewriteResultType(ArrayRef<ast::VariableDecl *> results); 366faf42264SRiver Riddle 367faf42264SRiver Riddle /// Create a PDLL (i.e. non-native) UserConstraintDecl or UserRewriteDecl. 368faf42264SRiver Riddle template <typename T> 369faf42264SRiver Riddle FailureOr<T *> createUserPDLLConstraintOrRewriteDecl( 370faf42264SRiver Riddle const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments, 371faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType, 372faf42264SRiver Riddle ast::CompoundStmt *body); 373faf42264SRiver Riddle 37411d26bd1SRiver Riddle /// Try to create a variable decl with the given components, returning the 37511d26bd1SRiver Riddle /// Variable on success. 37611d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> 3776842ec42SRiver Riddle createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer, 37811d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints); 37911d26bd1SRiver Riddle 380faf42264SRiver Riddle /// Create a variable for an argument or result defined as part of the 381faf42264SRiver Riddle /// signature of a UserConstraintDecl/UserRewriteDecl. 382faf42264SRiver Riddle FailureOr<ast::VariableDecl *> 383faf42264SRiver Riddle createArgOrResultVariableDecl(StringRef name, SMRange loc, 384faf42264SRiver Riddle const ast::ConstraintRef &constraint); 385faf42264SRiver Riddle 38611d26bd1SRiver Riddle /// Validate the constraints used to constraint a variable decl. 38711d26bd1SRiver Riddle /// `inferredType` is the type of the variable inferred by the constraints 38811d26bd1SRiver Riddle /// within the list, and is updated to the most refined type as determined by 38911d26bd1SRiver Riddle /// the constraints. Returns success if the constraint list is valid, failure 390b6ec1de7SRiver Riddle /// otherwise. 39111d26bd1SRiver Riddle LogicalResult 39211d26bd1SRiver Riddle validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints, 393b6ec1de7SRiver Riddle ast::Type &inferredType); 39411d26bd1SRiver Riddle /// Validate a single reference to a constraint. `inferredType` contains the 39511d26bd1SRiver Riddle /// currently inferred variabled type and is refined within the type defined 39611d26bd1SRiver Riddle /// by the constraint. Returns success if the constraint is valid, failure 397b6ec1de7SRiver Riddle /// otherwise. 39811d26bd1SRiver Riddle LogicalResult validateVariableConstraint(const ast::ConstraintRef &ref, 399b6ec1de7SRiver Riddle ast::Type &inferredType); 40011d26bd1SRiver Riddle LogicalResult validateTypeConstraintExpr(const ast::Expr *typeExpr); 40111d26bd1SRiver Riddle LogicalResult validateTypeRangeConstraintExpr(const ast::Expr *typeExpr); 40211d26bd1SRiver Riddle 40311d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 40411d26bd1SRiver Riddle // Exprs 40511d26bd1SRiver Riddle 406faf42264SRiver Riddle FailureOr<ast::CallExpr *> 407faf42264SRiver Riddle createCallExpr(SMRange loc, ast::Expr *parentExpr, 408930916c7SMogball MutableArrayRef<ast::Expr *> arguments, 409930916c7SMogball bool isNegated = false); 410faf42264SRiver Riddle FailureOr<ast::DeclRefExpr *> createDeclRefExpr(SMRange loc, ast::Decl *decl); 41111d26bd1SRiver Riddle FailureOr<ast::DeclRefExpr *> 4126842ec42SRiver Riddle createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc, 41311d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints); 41411d26bd1SRiver Riddle FailureOr<ast::MemberAccessExpr *> 415faf42264SRiver Riddle createMemberAccessExpr(ast::Expr *parentExpr, StringRef name, SMRange loc); 41611d26bd1SRiver Riddle 41711d26bd1SRiver Riddle /// Validate the member access `name` into the given parent expression. On 41811d26bd1SRiver Riddle /// success, this also returns the type of the member accessed. 41911d26bd1SRiver Riddle FailureOr<ast::Type> validateMemberAccess(ast::Expr *parentExpr, 4206842ec42SRiver Riddle StringRef name, SMRange loc); 42102670c3fSRiver Riddle FailureOr<ast::OperationExpr *> 4226842ec42SRiver Riddle createOperationExpr(SMRange loc, const ast::OpNameDecl *name, 42391b8d96fSRiver Riddle OpResultTypeContext resultTypeContext, 424ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &operands, 42502670c3fSRiver Riddle MutableArrayRef<ast::NamedAttributeDecl *> attributes, 426ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &results); 42702670c3fSRiver Riddle LogicalResult 4280a81ace0SKazu Hirata validateOperationOperands(SMRange loc, std::optional<StringRef> name, 42981f2f4dfSRiver Riddle const ods::Operation *odsOp, 430ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &operands); 4310a81ace0SKazu Hirata LogicalResult validateOperationResults(SMRange loc, 4320a81ace0SKazu Hirata std::optional<StringRef> name, 43381f2f4dfSRiver Riddle const ods::Operation *odsOp, 434ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &results); 43591b8d96fSRiver Riddle void checkOperationResultTypeInferrence(SMRange loc, StringRef name, 43691b8d96fSRiver Riddle const ods::Operation *odsOp); 43781f2f4dfSRiver Riddle LogicalResult validateOperationOperandsOrResults( 4380a81ace0SKazu Hirata StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc, 4390a81ace0SKazu Hirata std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values, 44081f2f4dfSRiver Riddle ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy, 441ec92a125SRiver Riddle ast::RangeType rangeTy); 4426842ec42SRiver Riddle FailureOr<ast::TupleExpr *> createTupleExpr(SMRange loc, 443f62a57a3SRiver Riddle ArrayRef<ast::Expr *> elements, 444f62a57a3SRiver Riddle ArrayRef<StringRef> elementNames); 44511d26bd1SRiver Riddle 44611d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 44711d26bd1SRiver Riddle // Stmts 44811d26bd1SRiver Riddle 449faf42264SRiver Riddle FailureOr<ast::EraseStmt *> createEraseStmt(SMRange loc, ast::Expr *rootOp); 45012eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *> 4516842ec42SRiver Riddle createReplaceStmt(SMRange loc, ast::Expr *rootOp, 45212eebb8eSRiver Riddle MutableArrayRef<ast::Expr *> replValues); 4533ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *> 4546842ec42SRiver Riddle createRewriteStmt(SMRange loc, ast::Expr *rootOp, 4553ee44cb7SRiver Riddle ast::CompoundStmt *rewriteBody); 45611d26bd1SRiver Riddle 45711d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 458008de486SRiver Riddle // Code Completion 459008de486SRiver Riddle //===--------------------------------------------------------------------===// 460008de486SRiver Riddle 461008de486SRiver Riddle /// The set of various code completion methods. Every completion method 462008de486SRiver Riddle /// returns `failure` to stop the parsing process after providing completion 463008de486SRiver Riddle /// results. 464008de486SRiver Riddle 465008de486SRiver Riddle LogicalResult codeCompleteMemberAccess(ast::Expr *parentExpr); 4660a81ace0SKazu Hirata LogicalResult codeCompleteAttributeName(std::optional<StringRef> opName); 467008de486SRiver Riddle LogicalResult codeCompleteConstraintName(ast::Type inferredType, 468008de486SRiver Riddle bool allowInlineTypeConstraints); 469008de486SRiver Riddle LogicalResult codeCompleteDialectName(); 470008de486SRiver Riddle LogicalResult codeCompleteOperationName(StringRef dialectName); 471008de486SRiver Riddle LogicalResult codeCompletePatternMetadata(); 47241d2c6dfSRiver Riddle LogicalResult codeCompleteIncludeFilename(StringRef curPath); 473008de486SRiver Riddle 474469c5894SRiver Riddle void codeCompleteCallSignature(ast::Node *parent, unsigned currentNumArgs); 4750a81ace0SKazu Hirata void codeCompleteOperationOperandsSignature(std::optional<StringRef> opName, 476469c5894SRiver Riddle unsigned currentNumOperands); 4770a81ace0SKazu Hirata void codeCompleteOperationResultsSignature(std::optional<StringRef> opName, 478469c5894SRiver Riddle unsigned currentNumResults); 479469c5894SRiver Riddle 480008de486SRiver Riddle //===--------------------------------------------------------------------===// 48111d26bd1SRiver Riddle // Lexer Utilities 48211d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 48311d26bd1SRiver Riddle 48411d26bd1SRiver Riddle /// If the current token has the specified kind, consume it and return true. 48511d26bd1SRiver Riddle /// If not, return false. 48611d26bd1SRiver Riddle bool consumeIf(Token::Kind kind) { 48711d26bd1SRiver Riddle if (curToken.isNot(kind)) 48811d26bd1SRiver Riddle return false; 48911d26bd1SRiver Riddle consumeToken(kind); 49011d26bd1SRiver Riddle return true; 49111d26bd1SRiver Riddle } 49211d26bd1SRiver Riddle 49311d26bd1SRiver Riddle /// Advance the current lexer onto the next token. 49411d26bd1SRiver Riddle void consumeToken() { 49511d26bd1SRiver Riddle assert(curToken.isNot(Token::eof, Token::error) && 49611d26bd1SRiver Riddle "shouldn't advance past EOF or errors"); 49711d26bd1SRiver Riddle curToken = lexer.lexToken(); 49811d26bd1SRiver Riddle } 49911d26bd1SRiver Riddle 50011d26bd1SRiver Riddle /// Advance the current lexer onto the next token, asserting what the expected 50111d26bd1SRiver Riddle /// current token is. This is preferred to the above method because it leads 50211d26bd1SRiver Riddle /// to more self-documenting code with better checking. 50311d26bd1SRiver Riddle void consumeToken(Token::Kind kind) { 50411d26bd1SRiver Riddle assert(curToken.is(kind) && "consumed an unexpected token"); 50511d26bd1SRiver Riddle consumeToken(); 50611d26bd1SRiver Riddle } 50711d26bd1SRiver Riddle 508d7e7fdf3SRiver Riddle /// Reset the lexer to the location at the given position. 5096842ec42SRiver Riddle void resetToken(SMRange tokLoc) { 510d7e7fdf3SRiver Riddle lexer.resetPointer(tokLoc.Start.getPointer()); 511d7e7fdf3SRiver Riddle curToken = lexer.lexToken(); 512d7e7fdf3SRiver Riddle } 513d7e7fdf3SRiver Riddle 51411d26bd1SRiver Riddle /// Consume the specified token if present and return success. On failure, 51511d26bd1SRiver Riddle /// output a diagnostic and return failure. 51611d26bd1SRiver Riddle LogicalResult parseToken(Token::Kind kind, const Twine &msg) { 51711d26bd1SRiver Riddle if (curToken.getKind() != kind) 51811d26bd1SRiver Riddle return emitError(curToken.getLoc(), msg); 51911d26bd1SRiver Riddle consumeToken(); 52011d26bd1SRiver Riddle return success(); 52111d26bd1SRiver Riddle } 5226842ec42SRiver Riddle LogicalResult emitError(SMRange loc, const Twine &msg) { 52311d26bd1SRiver Riddle lexer.emitError(loc, msg); 52411d26bd1SRiver Riddle return failure(); 52511d26bd1SRiver Riddle } 52611d26bd1SRiver Riddle LogicalResult emitError(const Twine &msg) { 52711d26bd1SRiver Riddle return emitError(curToken.getLoc(), msg); 52811d26bd1SRiver Riddle } 529faf42264SRiver Riddle LogicalResult emitErrorAndNote(SMRange loc, const Twine &msg, SMRange noteLoc, 530faf42264SRiver Riddle const Twine ¬e) { 53111d26bd1SRiver Riddle lexer.emitErrorAndNote(loc, msg, noteLoc, note); 53211d26bd1SRiver Riddle return failure(); 53311d26bd1SRiver Riddle } 53411d26bd1SRiver Riddle 53511d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 53611d26bd1SRiver Riddle // Fields 53711d26bd1SRiver Riddle //===--------------------------------------------------------------------===// 53811d26bd1SRiver Riddle 53911d26bd1SRiver Riddle /// The owning AST context. 54011d26bd1SRiver Riddle ast::Context &ctx; 54111d26bd1SRiver Riddle 54211d26bd1SRiver Riddle /// The lexer of this parser. 54311d26bd1SRiver Riddle Lexer lexer; 54411d26bd1SRiver Riddle 54511d26bd1SRiver Riddle /// The current token within the lexer. 54611d26bd1SRiver Riddle Token curToken; 54711d26bd1SRiver Riddle 548bf352e0bSRiver Riddle /// A flag indicating if the parser should add documentation to AST nodes when 549bf352e0bSRiver Riddle /// viable. 550bf352e0bSRiver Riddle bool enableDocumentation; 551bf352e0bSRiver Riddle 55211d26bd1SRiver Riddle /// The most recently defined decl scope. 553671e30a1SMehdi Amini ast::DeclScope *curDeclScope = nullptr; 55411d26bd1SRiver Riddle llvm::SpecificBumpPtrAllocator<ast::DeclScope> scopeAllocator; 55511d26bd1SRiver Riddle 55611d26bd1SRiver Riddle /// The current context of the parser. 55711d26bd1SRiver Riddle ParserContext parserContext = ParserContext::Global; 55811d26bd1SRiver Riddle 55911d26bd1SRiver Riddle /// Cached types to simplify verification and expression creation. 5609e57210aSRiver Riddle ast::Type typeTy, valueTy; 5619e57210aSRiver Riddle ast::RangeType typeRangeTy, valueRangeTy; 56281f2f4dfSRiver Riddle ast::Type attrTy; 563faf42264SRiver Riddle 564faf42264SRiver Riddle /// A counter used when naming anonymous constraints and rewrites. 565faf42264SRiver Riddle unsigned anonymousDeclNameCounter = 0; 566008de486SRiver Riddle 567008de486SRiver Riddle /// The optional code completion context. 568008de486SRiver Riddle CodeCompleteContext *codeCompleteContext; 56911d26bd1SRiver Riddle }; 57011d26bd1SRiver Riddle } // namespace 57111d26bd1SRiver Riddle 57211d26bd1SRiver Riddle FailureOr<ast::Module *> Parser::parseModule() { 5736842ec42SRiver Riddle SMLoc moduleLoc = curToken.getStartLoc(); 57411d26bd1SRiver Riddle pushDeclScope(); 57511d26bd1SRiver Riddle 57611d26bd1SRiver Riddle // Parse the top-level decls of the module. 57711d26bd1SRiver Riddle SmallVector<ast::Decl *> decls; 57811d26bd1SRiver Riddle if (failed(parseModuleBody(decls))) 57911d26bd1SRiver Riddle return popDeclScope(), failure(); 58011d26bd1SRiver Riddle 58111d26bd1SRiver Riddle popDeclScope(); 58211d26bd1SRiver Riddle return ast::Module::create(ctx, moduleLoc, decls); 58311d26bd1SRiver Riddle } 58411d26bd1SRiver Riddle 58581f2f4dfSRiver Riddle LogicalResult Parser::parseModuleBody(SmallVectorImpl<ast::Decl *> &decls) { 58611d26bd1SRiver Riddle while (curToken.isNot(Token::eof)) { 58711d26bd1SRiver Riddle if (curToken.is(Token::directive)) { 58811d26bd1SRiver Riddle if (failed(parseDirective(decls))) 58911d26bd1SRiver Riddle return failure(); 59011d26bd1SRiver Riddle continue; 59111d26bd1SRiver Riddle } 59211d26bd1SRiver Riddle 59311d26bd1SRiver Riddle FailureOr<ast::Decl *> decl = parseTopLevelDecl(); 59411d26bd1SRiver Riddle if (failed(decl)) 59511d26bd1SRiver Riddle return failure(); 59611d26bd1SRiver Riddle decls.push_back(*decl); 59711d26bd1SRiver Riddle } 59811d26bd1SRiver Riddle return success(); 59911d26bd1SRiver Riddle } 60011d26bd1SRiver Riddle 60102670c3fSRiver Riddle ast::Expr *Parser::convertOpToValue(const ast::Expr *opExpr) { 60202670c3fSRiver Riddle return ast::AllResultsMemberAccessExpr::create(ctx, opExpr->getLoc(), opExpr, 60302670c3fSRiver Riddle valueRangeTy); 60402670c3fSRiver Riddle } 60502670c3fSRiver Riddle 60611d26bd1SRiver Riddle LogicalResult Parser::convertExpressionTo( 60711d26bd1SRiver Riddle ast::Expr *&expr, ast::Type type, 60811d26bd1SRiver Riddle function_ref<void(ast::Diagnostic &diag)> noteAttachFn) { 60911d26bd1SRiver Riddle ast::Type exprType = expr->getType(); 61011d26bd1SRiver Riddle if (exprType == type) 61111d26bd1SRiver Riddle return success(); 61211d26bd1SRiver Riddle 61311d26bd1SRiver Riddle auto emitConvertError = [&]() -> ast::InFlightDiagnostic { 61411d26bd1SRiver Riddle ast::InFlightDiagnostic diag = ctx.getDiagEngine().emitError( 61511d26bd1SRiver Riddle expr->getLoc(), llvm::formatv("unable to convert expression of type " 61611d26bd1SRiver Riddle "`{0}` to the expected type of " 61711d26bd1SRiver Riddle "`{1}`", 61811d26bd1SRiver Riddle exprType, type)); 61911d26bd1SRiver Riddle if (noteAttachFn) 62011d26bd1SRiver Riddle noteAttachFn(*diag); 62111d26bd1SRiver Riddle return diag; 62211d26bd1SRiver Riddle }; 62311d26bd1SRiver Riddle 624d2353695SPeiming Liu if (auto exprOpType = dyn_cast<ast::OperationType>(exprType)) 6259e57210aSRiver Riddle return convertOpExpressionTo(expr, exprOpType, type, emitConvertError); 6269e57210aSRiver Riddle 6279e57210aSRiver Riddle // FIXME: Decide how to allow/support converting a single result to multiple, 6289e57210aSRiver Riddle // and multiple to a single result. For now, we just allow Single->Range, 6299e57210aSRiver Riddle // but this isn't something really supported in the PDL dialect. We should 6309e57210aSRiver Riddle // figure out some way to support both. 6319e57210aSRiver Riddle if ((exprType == valueTy || exprType == valueRangeTy) && 6329e57210aSRiver Riddle (type == valueTy || type == valueRangeTy)) 6339e57210aSRiver Riddle return success(); 6349e57210aSRiver Riddle if ((exprType == typeTy || exprType == typeRangeTy) && 6359e57210aSRiver Riddle (type == typeTy || type == typeRangeTy)) 6369e57210aSRiver Riddle return success(); 6379e57210aSRiver Riddle 6389e57210aSRiver Riddle // Handle tuple types. 639d2353695SPeiming Liu if (auto exprTupleType = dyn_cast<ast::TupleType>(exprType)) 6409e57210aSRiver Riddle return convertTupleExpressionTo(expr, exprTupleType, type, emitConvertError, 6419e57210aSRiver Riddle noteAttachFn); 6429e57210aSRiver Riddle 6439e57210aSRiver Riddle return emitConvertError(); 6449e57210aSRiver Riddle } 6459e57210aSRiver Riddle 6469e57210aSRiver Riddle LogicalResult Parser::convertOpExpressionTo( 6479e57210aSRiver Riddle ast::Expr *&expr, ast::OperationType exprType, ast::Type type, 6489e57210aSRiver Riddle function_ref<ast::InFlightDiagnostic()> emitErrorFn) { 64911d26bd1SRiver Riddle // Two operation types are compatible if they have the same name, or if the 65011d26bd1SRiver Riddle // expected type is more general. 651d2353695SPeiming Liu if (auto opType = dyn_cast<ast::OperationType>(type)) { 65211d26bd1SRiver Riddle if (opType.getName()) 6539e57210aSRiver Riddle return emitErrorFn(); 65411d26bd1SRiver Riddle return success(); 65511d26bd1SRiver Riddle } 65611d26bd1SRiver Riddle 65711d26bd1SRiver Riddle // An operation can always convert to a ValueRange. 65811d26bd1SRiver Riddle if (type == valueRangeTy) { 65902670c3fSRiver Riddle expr = ast::AllResultsMemberAccessExpr::create(ctx, expr->getLoc(), expr, 66002670c3fSRiver Riddle valueRangeTy); 66111d26bd1SRiver Riddle return success(); 66211d26bd1SRiver Riddle } 66311d26bd1SRiver Riddle 66411d26bd1SRiver Riddle // Allow conversion to a single value by constraining the result range. 66511d26bd1SRiver Riddle if (type == valueTy) { 66681f2f4dfSRiver Riddle // If the operation is registered, we can verify if it can ever have a 66781f2f4dfSRiver Riddle // single result. 6689e57210aSRiver Riddle if (const ods::Operation *odsOp = exprType.getODSOperation()) { 66981f2f4dfSRiver Riddle if (odsOp->getResults().empty()) { 6709e57210aSRiver Riddle return emitErrorFn()->attachNote( 67181f2f4dfSRiver Riddle llvm::formatv("see the definition of `{0}`, which was defined " 67281f2f4dfSRiver Riddle "with zero results", 67381f2f4dfSRiver Riddle odsOp->getName()), 67481f2f4dfSRiver Riddle odsOp->getLoc()); 67581f2f4dfSRiver Riddle } 67681f2f4dfSRiver Riddle 67781f2f4dfSRiver Riddle unsigned numSingleResults = llvm::count_if( 67881f2f4dfSRiver Riddle odsOp->getResults(), [](const ods::OperandOrResult &result) { 67981f2f4dfSRiver Riddle return result.getVariableLengthKind() == 68081f2f4dfSRiver Riddle ods::VariableLengthKind::Single; 68181f2f4dfSRiver Riddle }); 68281f2f4dfSRiver Riddle if (numSingleResults > 1) { 6839e57210aSRiver Riddle return emitErrorFn()->attachNote( 68481f2f4dfSRiver Riddle llvm::formatv("see the definition of `{0}`, which was defined " 68581f2f4dfSRiver Riddle "with at least {1} results", 68681f2f4dfSRiver Riddle odsOp->getName(), numSingleResults), 68781f2f4dfSRiver Riddle odsOp->getLoc()); 68881f2f4dfSRiver Riddle } 68981f2f4dfSRiver Riddle } 69081f2f4dfSRiver Riddle 69102670c3fSRiver Riddle expr = ast::AllResultsMemberAccessExpr::create(ctx, expr->getLoc(), expr, 69202670c3fSRiver Riddle valueTy); 69311d26bd1SRiver Riddle return success(); 69411d26bd1SRiver Riddle } 6959e57210aSRiver Riddle return emitErrorFn(); 69611d26bd1SRiver Riddle } 69711d26bd1SRiver Riddle 6989e57210aSRiver Riddle LogicalResult Parser::convertTupleExpressionTo( 6999e57210aSRiver Riddle ast::Expr *&expr, ast::TupleType exprType, ast::Type type, 7009e57210aSRiver Riddle function_ref<ast::InFlightDiagnostic()> emitErrorFn, 7019e57210aSRiver Riddle function_ref<void(ast::Diagnostic &diag)> noteAttachFn) { 7029e57210aSRiver Riddle // Handle conversions between tuples. 703d2353695SPeiming Liu if (auto tupleType = dyn_cast<ast::TupleType>(type)) { 7049e57210aSRiver Riddle if (tupleType.size() != exprType.size()) 7059e57210aSRiver Riddle return emitErrorFn(); 706f62a57a3SRiver Riddle 707f62a57a3SRiver Riddle // Build a new tuple expression using each of the elements of the current 708f62a57a3SRiver Riddle // tuple. 709f62a57a3SRiver Riddle SmallVector<ast::Expr *> newExprs; 7109e57210aSRiver Riddle for (unsigned i = 0, e = exprType.size(); i < e; ++i) { 711f62a57a3SRiver Riddle newExprs.push_back(ast::MemberAccessExpr::create( 712f62a57a3SRiver Riddle ctx, expr->getLoc(), expr, llvm::to_string(i), 7139e57210aSRiver Riddle exprType.getElementTypes()[i])); 714f62a57a3SRiver Riddle 715f62a57a3SRiver Riddle auto diagFn = [&](ast::Diagnostic &diag) { 716f62a57a3SRiver Riddle diag.attachNote(llvm::formatv("when converting element #{0} of `{1}`", 7179e57210aSRiver Riddle i, exprType)); 718f62a57a3SRiver Riddle if (noteAttachFn) 719f62a57a3SRiver Riddle noteAttachFn(diag); 720f62a57a3SRiver Riddle }; 721f62a57a3SRiver Riddle if (failed(convertExpressionTo(newExprs.back(), 722f62a57a3SRiver Riddle tupleType.getElementTypes()[i], diagFn))) 723f62a57a3SRiver Riddle return failure(); 724f62a57a3SRiver Riddle } 725f62a57a3SRiver Riddle expr = ast::TupleExpr::create(ctx, expr->getLoc(), newExprs, 726f62a57a3SRiver Riddle tupleType.getElementNames()); 727f62a57a3SRiver Riddle return success(); 728f62a57a3SRiver Riddle } 729f62a57a3SRiver Riddle 7309e57210aSRiver Riddle // Handle conversion to a range. 7319e57210aSRiver Riddle auto convertToRange = [&](ArrayRef<ast::Type> allowedElementTypes, 7329e57210aSRiver Riddle ast::RangeType resultTy) -> LogicalResult { 7339e57210aSRiver Riddle // TODO: We currently only allow range conversion within a rewrite context. 7349e57210aSRiver Riddle if (parserContext != ParserContext::Rewrite) { 7359e57210aSRiver Riddle return emitErrorFn()->attachNote("Tuple to Range conversion is currently " 7369e57210aSRiver Riddle "only allowed within a rewrite context"); 7379e57210aSRiver Riddle } 7389e57210aSRiver Riddle 7399e57210aSRiver Riddle // All of the tuple elements must be allowed types. 7409e57210aSRiver Riddle for (ast::Type elementType : exprType.getElementTypes()) 7419e57210aSRiver Riddle if (!llvm::is_contained(allowedElementTypes, elementType)) 7429e57210aSRiver Riddle return emitErrorFn(); 7439e57210aSRiver Riddle 7449e57210aSRiver Riddle // Build a new tuple expression using each of the elements of the current 7459e57210aSRiver Riddle // tuple. 7469e57210aSRiver Riddle SmallVector<ast::Expr *> newExprs; 7479e57210aSRiver Riddle for (unsigned i = 0, e = exprType.size(); i < e; ++i) { 7489e57210aSRiver Riddle newExprs.push_back(ast::MemberAccessExpr::create( 7499e57210aSRiver Riddle ctx, expr->getLoc(), expr, llvm::to_string(i), 7509e57210aSRiver Riddle exprType.getElementTypes()[i])); 7519e57210aSRiver Riddle } 7529e57210aSRiver Riddle expr = ast::RangeExpr::create(ctx, expr->getLoc(), newExprs, resultTy); 7539e57210aSRiver Riddle return success(); 7549e57210aSRiver Riddle }; 7559e57210aSRiver Riddle if (type == valueRangeTy) 7569e57210aSRiver Riddle return convertToRange({valueTy, valueRangeTy}, valueRangeTy); 7579e57210aSRiver Riddle if (type == typeRangeTy) 7589e57210aSRiver Riddle return convertToRange({typeTy, typeRangeTy}, typeRangeTy); 7599e57210aSRiver Riddle 7609e57210aSRiver Riddle return emitErrorFn(); 76111d26bd1SRiver Riddle } 76211d26bd1SRiver Riddle 76311d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 76411d26bd1SRiver Riddle // Directives 76511d26bd1SRiver Riddle 76681f2f4dfSRiver Riddle LogicalResult Parser::parseDirective(SmallVectorImpl<ast::Decl *> &decls) { 76711d26bd1SRiver Riddle StringRef directive = curToken.getSpelling(); 76811d26bd1SRiver Riddle if (directive == "#include") 76911d26bd1SRiver Riddle return parseInclude(decls); 77011d26bd1SRiver Riddle 77111d26bd1SRiver Riddle return emitError("unknown directive `" + directive + "`"); 77211d26bd1SRiver Riddle } 77311d26bd1SRiver Riddle 77481f2f4dfSRiver Riddle LogicalResult Parser::parseInclude(SmallVectorImpl<ast::Decl *> &decls) { 7756842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 77611d26bd1SRiver Riddle consumeToken(Token::directive); 77711d26bd1SRiver Riddle 77841d2c6dfSRiver Riddle // Handle code completion of the include file path. 77941d2c6dfSRiver Riddle if (curToken.is(Token::code_complete_string)) 78041d2c6dfSRiver Riddle return codeCompleteIncludeFilename(curToken.getStringValue()); 78141d2c6dfSRiver Riddle 78211d26bd1SRiver Riddle // Parse the file being included. 78311d26bd1SRiver Riddle if (!curToken.isString()) 78411d26bd1SRiver Riddle return emitError(loc, 78511d26bd1SRiver Riddle "expected string file name after `include` directive"); 7866842ec42SRiver Riddle SMRange fileLoc = curToken.getLoc(); 78711d26bd1SRiver Riddle std::string filenameStr = curToken.getStringValue(); 78811d26bd1SRiver Riddle StringRef filename = filenameStr; 78911d26bd1SRiver Riddle consumeToken(); 79011d26bd1SRiver Riddle 79111d26bd1SRiver Riddle // Check the type of include. If ending with `.pdll`, this is another pdl file 79211d26bd1SRiver Riddle // to be parsed along with the current module. 79388d319a2SKazu Hirata if (filename.ends_with(".pdll")) { 79409af7fefSRiver Riddle if (failed(lexer.pushInclude(filename, fileLoc))) 79511d26bd1SRiver Riddle return emitError(fileLoc, 79611d26bd1SRiver Riddle "unable to open include file `" + filename + "`"); 79711d26bd1SRiver Riddle 79811d26bd1SRiver Riddle // If we added the include successfully, parse it into the current module. 79909af7fefSRiver Riddle // Make sure to update to the next token after we finish parsing the nested 80009af7fefSRiver Riddle // file. 80111d26bd1SRiver Riddle curToken = lexer.lexToken(); 80211d26bd1SRiver Riddle LogicalResult result = parseModuleBody(decls); 80309af7fefSRiver Riddle curToken = lexer.lexToken(); 80411d26bd1SRiver Riddle return result; 80511d26bd1SRiver Riddle } 80611d26bd1SRiver Riddle 80781f2f4dfSRiver Riddle // Otherwise, this must be a `.td` include. 80888d319a2SKazu Hirata if (filename.ends_with(".td")) 80981f2f4dfSRiver Riddle return parseTdInclude(filename, fileLoc, decls); 81081f2f4dfSRiver Riddle 81181f2f4dfSRiver Riddle return emitError(fileLoc, 81281f2f4dfSRiver Riddle "expected include filename to end with `.pdll` or `.td`"); 81381f2f4dfSRiver Riddle } 81481f2f4dfSRiver Riddle 81581f2f4dfSRiver Riddle LogicalResult Parser::parseTdInclude(StringRef filename, llvm::SMRange fileLoc, 81681f2f4dfSRiver Riddle SmallVectorImpl<ast::Decl *> &decls) { 81781f2f4dfSRiver Riddle llvm::SourceMgr &parserSrcMgr = lexer.getSourceMgr(); 81881f2f4dfSRiver Riddle 8195a9a438aSRiver Riddle // Use the source manager to open the file, but don't yet add it. 8205a9a438aSRiver Riddle std::string includedFile; 8215a9a438aSRiver Riddle llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> includeBuffer = 8225a9a438aSRiver Riddle parserSrcMgr.OpenIncludeFile(filename.str(), includedFile); 8235a9a438aSRiver Riddle if (!includeBuffer) 8245a9a438aSRiver Riddle return emitError(fileLoc, "unable to open include file `" + filename + "`"); 8255a9a438aSRiver Riddle 8265a9a438aSRiver Riddle // Setup the source manager for parsing the tablegen file. 8275a9a438aSRiver Riddle llvm::SourceMgr tdSrcMgr; 8285a9a438aSRiver Riddle tdSrcMgr.AddNewSourceBuffer(std::move(*includeBuffer), SMLoc()); 8295a9a438aSRiver Riddle tdSrcMgr.setIncludeDirs(parserSrcMgr.getIncludeDirs()); 8305a9a438aSRiver Riddle 83181f2f4dfSRiver Riddle // This class provides a context argument for the llvm::SourceMgr diagnostic 83281f2f4dfSRiver Riddle // handler. 83381f2f4dfSRiver Riddle struct DiagHandlerContext { 83481f2f4dfSRiver Riddle Parser &parser; 83581f2f4dfSRiver Riddle StringRef filename; 83681f2f4dfSRiver Riddle llvm::SMRange loc; 83781f2f4dfSRiver Riddle } handlerContext{*this, filename, fileLoc}; 83881f2f4dfSRiver Riddle 83981f2f4dfSRiver Riddle // Set the diagnostic handler for the tablegen source manager. 8405a9a438aSRiver Riddle tdSrcMgr.setDiagHandler( 84181f2f4dfSRiver Riddle [](const llvm::SMDiagnostic &diag, void *rawHandlerContext) { 84281f2f4dfSRiver Riddle auto *ctx = reinterpret_cast<DiagHandlerContext *>(rawHandlerContext); 84381f2f4dfSRiver Riddle (void)ctx->parser.emitError( 84481f2f4dfSRiver Riddle ctx->loc, 84581f2f4dfSRiver Riddle llvm::formatv("error while processing include file `{0}`: {1}", 84681f2f4dfSRiver Riddle ctx->filename, diag.getMessage())); 84781f2f4dfSRiver Riddle }, 84881f2f4dfSRiver Riddle &handlerContext); 84981f2f4dfSRiver Riddle 8505a9a438aSRiver Riddle // Parse the tablegen file. 8515a9a438aSRiver Riddle llvm::RecordKeeper tdRecords; 8525a9a438aSRiver Riddle if (llvm::TableGenParseFile(tdSrcMgr, tdRecords)) 85381f2f4dfSRiver Riddle return failure(); 85481f2f4dfSRiver Riddle 8555a9a438aSRiver Riddle // Process the parsed records. 8565a9a438aSRiver Riddle processTdIncludeRecords(tdRecords, decls); 8575a9a438aSRiver Riddle 8585a9a438aSRiver Riddle // After we are done processing, move all of the tablegen source buffers to 8595a9a438aSRiver Riddle // the main parser source mgr. This allows for directly using source locations 8605a9a438aSRiver Riddle // from the .td files without needing to remap them. 8615a9a438aSRiver Riddle parserSrcMgr.takeSourceBuffersFrom(tdSrcMgr, fileLoc.End); 86281f2f4dfSRiver Riddle return success(); 86381f2f4dfSRiver Riddle } 86481f2f4dfSRiver Riddle 865b60c6cbcSRahul Joshi void Parser::processTdIncludeRecords(const llvm::RecordKeeper &tdRecords, 86681f2f4dfSRiver Riddle SmallVectorImpl<ast::Decl *> &decls) { 86781f2f4dfSRiver Riddle // Return the length kind of the given value. 86881f2f4dfSRiver Riddle auto getLengthKind = [](const auto &value) { 86981f2f4dfSRiver Riddle if (value.isOptional()) 87081f2f4dfSRiver Riddle return ods::VariableLengthKind::Optional; 87181f2f4dfSRiver Riddle return value.isVariadic() ? ods::VariableLengthKind::Variadic 87281f2f4dfSRiver Riddle : ods::VariableLengthKind::Single; 87381f2f4dfSRiver Riddle }; 87481f2f4dfSRiver Riddle 87581f2f4dfSRiver Riddle // Insert a type constraint into the ODS context. 87681f2f4dfSRiver Riddle ods::Context &odsContext = ctx.getODSContext(); 87781f2f4dfSRiver Riddle auto addTypeConstraint = [&](const tblgen::NamedTypeConstraint &cst) 87881f2f4dfSRiver Riddle -> const ods::TypeConstraint & { 879bf352e0bSRiver Riddle return odsContext.insertTypeConstraint( 880bf352e0bSRiver Riddle cst.constraint.getUniqueDefName(), 88135f55f53SMatthias Springer processDoc(cst.constraint.getSummary()), cst.constraint.getCppType()); 88281f2f4dfSRiver Riddle }; 88381f2f4dfSRiver Riddle auto convertLocToRange = [&](llvm::SMLoc loc) -> llvm::SMRange { 88481f2f4dfSRiver Riddle return {loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)}; 88581f2f4dfSRiver Riddle }; 88681f2f4dfSRiver Riddle 88781f2f4dfSRiver Riddle // Process the parsed tablegen records to build ODS information. 88881f2f4dfSRiver Riddle /// Operations. 889b60c6cbcSRahul Joshi for (const llvm::Record *def : tdRecords.getAllDerivedDefinitions("Op")) { 89081f2f4dfSRiver Riddle tblgen::Operator op(def); 89181f2f4dfSRiver Riddle 89291b8d96fSRiver Riddle // Check to see if this operation is known to support type inferrence. 89391b8d96fSRiver Riddle bool supportsResultTypeInferrence = 89491b8d96fSRiver Riddle op.getTrait("::mlir::InferTypeOpInterface::Trait"); 89591b8d96fSRiver Riddle 8969fa59e76SBenjamin Kramer auto [odsOp, inserted] = odsContext.insertOperation( 897bf352e0bSRiver Riddle op.getOperationName(), processDoc(op.getSummary()), 898bf352e0bSRiver Riddle processAndFormatDoc(op.getDescription()), op.getQualCppClassName(), 899bf352e0bSRiver Riddle supportsResultTypeInferrence, op.getLoc().front()); 90081f2f4dfSRiver Riddle 90181f2f4dfSRiver Riddle // Ignore operations that have already been added. 90281f2f4dfSRiver Riddle if (!inserted) 90381f2f4dfSRiver Riddle continue; 90481f2f4dfSRiver Riddle 90581f2f4dfSRiver Riddle for (const tblgen::NamedAttribute &attr : op.getAttributes()) { 906bf352e0bSRiver Riddle odsOp->appendAttribute(attr.name, attr.attr.isOptional(), 907bf352e0bSRiver Riddle odsContext.insertAttributeConstraint( 908bf352e0bSRiver Riddle attr.attr.getUniqueDefName(), 909bf352e0bSRiver Riddle processDoc(attr.attr.getSummary()), 91081f2f4dfSRiver Riddle attr.attr.getStorageType())); 91181f2f4dfSRiver Riddle } 91281f2f4dfSRiver Riddle for (const tblgen::NamedTypeConstraint &operand : op.getOperands()) { 91381f2f4dfSRiver Riddle odsOp->appendOperand(operand.name, getLengthKind(operand), 91481f2f4dfSRiver Riddle addTypeConstraint(operand)); 91581f2f4dfSRiver Riddle } 91681f2f4dfSRiver Riddle for (const tblgen::NamedTypeConstraint &result : op.getResults()) { 91781f2f4dfSRiver Riddle odsOp->appendResult(result.name, getLengthKind(result), 91881f2f4dfSRiver Riddle addTypeConstraint(result)); 91981f2f4dfSRiver Riddle } 92081f2f4dfSRiver Riddle } 9219f186bb1SMarkus Böck 922b60c6cbcSRahul Joshi auto shouldBeSkipped = [this](const llvm::Record *def) { 9239f186bb1SMarkus Böck return def->isAnonymous() || curDeclScope->lookup(def->getName()) || 9249f186bb1SMarkus Böck def->isSubClassOf("DeclareInterfaceMethods"); 9259f186bb1SMarkus Böck }; 9269f186bb1SMarkus Böck 92781f2f4dfSRiver Riddle /// Attr constraints. 928b60c6cbcSRahul Joshi for (const llvm::Record *def : tdRecords.getAllDerivedDefinitions("Attr")) { 9299f186bb1SMarkus Böck if (shouldBeSkipped(def)) 9309f186bb1SMarkus Böck continue; 9319f186bb1SMarkus Böck 9321c2edb02SRiver Riddle tblgen::Attribute constraint(def); 9339f186bb1SMarkus Böck decls.push_back(createODSNativePDLLConstraintDecl<ast::AttrConstraintDecl>( 9341c2edb02SRiver Riddle constraint, convertLocToRange(def->getLoc().front()), attrTy, 9351c2edb02SRiver Riddle constraint.getStorageType())); 93681f2f4dfSRiver Riddle } 93781f2f4dfSRiver Riddle /// Type constraints. 938b60c6cbcSRahul Joshi for (const llvm::Record *def : tdRecords.getAllDerivedDefinitions("Type")) { 9399f186bb1SMarkus Böck if (shouldBeSkipped(def)) 9409f186bb1SMarkus Böck continue; 9419f186bb1SMarkus Böck 9421c2edb02SRiver Riddle tblgen::TypeConstraint constraint(def); 9439f186bb1SMarkus Böck decls.push_back(createODSNativePDLLConstraintDecl<ast::TypeConstraintDecl>( 9441c2edb02SRiver Riddle constraint, convertLocToRange(def->getLoc().front()), typeTy, 94535f55f53SMatthias Springer constraint.getCppType())); 94681f2f4dfSRiver Riddle } 9479f186bb1SMarkus Böck /// OpInterfaces. 94881f2f4dfSRiver Riddle ast::Type opTy = ast::OperationType::get(ctx); 949b60c6cbcSRahul Joshi for (const llvm::Record *def : 950b60c6cbcSRahul Joshi tdRecords.getAllDerivedDefinitions("OpInterface")) { 9519f186bb1SMarkus Böck if (shouldBeSkipped(def)) 95281f2f4dfSRiver Riddle continue; 9539f186bb1SMarkus Böck 95481f2f4dfSRiver Riddle SMRange loc = convertLocToRange(def->getLoc().front()); 95581f2f4dfSRiver Riddle 9561c2edb02SRiver Riddle std::string cppClassName = 9571c2edb02SRiver Riddle llvm::formatv("{0}::{1}", def->getValueAsString("cppNamespace"), 9589f186bb1SMarkus Böck def->getValueAsString("cppInterfaceName")) 9591c2edb02SRiver Riddle .str(); 96081f2f4dfSRiver Riddle std::string codeBlock = 9611c2edb02SRiver Riddle llvm::formatv("return ::mlir::success(llvm::isa<{0}>(self));", 9621c2edb02SRiver Riddle cppClassName) 96381f2f4dfSRiver Riddle .str(); 96481f2f4dfSRiver Riddle 965bf352e0bSRiver Riddle std::string desc = 966bf352e0bSRiver Riddle processAndFormatDoc(def->getValueAsString("description")); 96781f2f4dfSRiver Riddle decls.push_back(createODSNativePDLLConstraintDecl<ast::OpConstraintDecl>( 9689f186bb1SMarkus Böck def->getName(), codeBlock, loc, opTy, cppClassName, desc)); 96981f2f4dfSRiver Riddle } 97081f2f4dfSRiver Riddle } 97181f2f4dfSRiver Riddle 97281f2f4dfSRiver Riddle template <typename ConstraintT> 973bf352e0bSRiver Riddle ast::Decl *Parser::createODSNativePDLLConstraintDecl( 974bf352e0bSRiver Riddle StringRef name, StringRef codeBlock, SMRange loc, ast::Type type, 975bf352e0bSRiver Riddle StringRef nativeType, StringRef docString) { 97681f2f4dfSRiver Riddle // Build the single input parameter. 97781f2f4dfSRiver Riddle ast::DeclScope *argScope = pushDeclScope(); 97881f2f4dfSRiver Riddle auto *paramVar = ast::VariableDecl::create( 97981f2f4dfSRiver Riddle ctx, ast::Name::create(ctx, "self", loc), type, 98081f2f4dfSRiver Riddle /*initExpr=*/nullptr, ast::ConstraintRef(ConstraintT::create(ctx, loc))); 98181f2f4dfSRiver Riddle argScope->add(paramVar); 98281f2f4dfSRiver Riddle popDeclScope(); 98381f2f4dfSRiver Riddle 98481f2f4dfSRiver Riddle // Build the native constraint. 98581f2f4dfSRiver Riddle auto *constraintDecl = ast::UserConstraintDecl::createNative( 98681f2f4dfSRiver Riddle ctx, ast::Name::create(ctx, name, loc), paramVar, 9871a36588eSKazu Hirata /*results=*/std::nullopt, codeBlock, ast::TupleType::get(ctx), 9881a36588eSKazu Hirata nativeType); 989bf352e0bSRiver Riddle constraintDecl->setDocComment(ctx, docString); 99081f2f4dfSRiver Riddle curDeclScope->add(constraintDecl); 99181f2f4dfSRiver Riddle return constraintDecl; 99281f2f4dfSRiver Riddle } 99381f2f4dfSRiver Riddle 99481f2f4dfSRiver Riddle template <typename ConstraintT> 99581f2f4dfSRiver Riddle ast::Decl * 99681f2f4dfSRiver Riddle Parser::createODSNativePDLLConstraintDecl(const tblgen::Constraint &constraint, 9971c2edb02SRiver Riddle SMRange loc, ast::Type type, 9981c2edb02SRiver Riddle StringRef nativeType) { 99981f2f4dfSRiver Riddle // Format the condition template. 100081f2f4dfSRiver Riddle tblgen::FmtContext fmtContext; 100181f2f4dfSRiver Riddle fmtContext.withSelf("self"); 1002651d9f70SRiver Riddle std::string codeBlock = tblgen::tgfmt( 1003651d9f70SRiver Riddle "return ::mlir::success(" + constraint.getConditionTemplate() + ");", 1004651d9f70SRiver Riddle &fmtContext); 100581f2f4dfSRiver Riddle 1006bf352e0bSRiver Riddle // If documentation was enabled, build the doc string for the generated 1007bf352e0bSRiver Riddle // constraint. It would be nice to do this lazily, but TableGen information is 1008bf352e0bSRiver Riddle // destroyed after we finish parsing the file. 1009bf352e0bSRiver Riddle std::string docString; 1010bf352e0bSRiver Riddle if (enableDocumentation) { 1011bf352e0bSRiver Riddle StringRef desc = constraint.getDescription(); 1012bf352e0bSRiver Riddle docString = processAndFormatDoc( 1013bf352e0bSRiver Riddle constraint.getSummary() + 1014bf352e0bSRiver Riddle (desc.empty() ? "" : ("\n\n" + constraint.getDescription()))); 1015bf352e0bSRiver Riddle } 1016bf352e0bSRiver Riddle 1017b3fc0fa8SRiver Riddle return createODSNativePDLLConstraintDecl<ConstraintT>( 1018bf352e0bSRiver Riddle constraint.getUniqueDefName(), codeBlock, loc, type, nativeType, 1019bf352e0bSRiver Riddle docString); 102011d26bd1SRiver Riddle } 102111d26bd1SRiver Riddle 102211d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 102311d26bd1SRiver Riddle // Decls 102411d26bd1SRiver Riddle 102511d26bd1SRiver Riddle FailureOr<ast::Decl *> Parser::parseTopLevelDecl() { 102611d26bd1SRiver Riddle FailureOr<ast::Decl *> decl; 102711d26bd1SRiver Riddle switch (curToken.getKind()) { 1028faf42264SRiver Riddle case Token::kw_Constraint: 1029faf42264SRiver Riddle decl = parseUserConstraintDecl(); 1030faf42264SRiver Riddle break; 103111d26bd1SRiver Riddle case Token::kw_Pattern: 103211d26bd1SRiver Riddle decl = parsePatternDecl(); 103311d26bd1SRiver Riddle break; 1034faf42264SRiver Riddle case Token::kw_Rewrite: 1035faf42264SRiver Riddle decl = parseUserRewriteDecl(); 1036faf42264SRiver Riddle break; 103711d26bd1SRiver Riddle default: 103811d26bd1SRiver Riddle return emitError("expected top-level declaration, such as a `Pattern`"); 103911d26bd1SRiver Riddle } 104011d26bd1SRiver Riddle if (failed(decl)) 104111d26bd1SRiver Riddle return failure(); 104211d26bd1SRiver Riddle 104311d26bd1SRiver Riddle // If the decl has a name, add it to the current scope. 104411d26bd1SRiver Riddle if (const ast::Name *name = (*decl)->getName()) { 104511d26bd1SRiver Riddle if (failed(checkDefineNamedDecl(*name))) 104611d26bd1SRiver Riddle return failure(); 104711d26bd1SRiver Riddle curDeclScope->add(*decl); 104811d26bd1SRiver Riddle } 104911d26bd1SRiver Riddle return decl; 105011d26bd1SRiver Riddle } 105111d26bd1SRiver Riddle 1052008de486SRiver Riddle FailureOr<ast::NamedAttributeDecl *> 10530a81ace0SKazu Hirata Parser::parseNamedAttributeDecl(std::optional<StringRef> parentOpName) { 1054008de486SRiver Riddle // Check for name code completion. 1055008de486SRiver Riddle if (curToken.is(Token::code_complete)) 1056008de486SRiver Riddle return codeCompleteAttributeName(parentOpName); 1057008de486SRiver Riddle 105802670c3fSRiver Riddle std::string attrNameStr; 105902670c3fSRiver Riddle if (curToken.isString()) 106002670c3fSRiver Riddle attrNameStr = curToken.getStringValue(); 106102670c3fSRiver Riddle else if (curToken.is(Token::identifier) || curToken.isKeyword()) 106202670c3fSRiver Riddle attrNameStr = curToken.getSpelling().str(); 106302670c3fSRiver Riddle else 106402670c3fSRiver Riddle return emitError("expected identifier or string attribute name"); 106502670c3fSRiver Riddle const auto &name = ast::Name::create(ctx, attrNameStr, curToken.getLoc()); 106602670c3fSRiver Riddle consumeToken(); 106702670c3fSRiver Riddle 106802670c3fSRiver Riddle // Check for a value of the attribute. 106902670c3fSRiver Riddle ast::Expr *attrValue = nullptr; 107002670c3fSRiver Riddle if (consumeIf(Token::equal)) { 107102670c3fSRiver Riddle FailureOr<ast::Expr *> attrExpr = parseExpr(); 107202670c3fSRiver Riddle if (failed(attrExpr)) 107302670c3fSRiver Riddle return failure(); 107402670c3fSRiver Riddle attrValue = *attrExpr; 107502670c3fSRiver Riddle } else { 107602670c3fSRiver Riddle // If there isn't a concrete value, create an expression representing a 107702670c3fSRiver Riddle // UnitAttr. 107802670c3fSRiver Riddle attrValue = ast::AttributeExpr::create(ctx, name.getLoc(), "unit"); 107902670c3fSRiver Riddle } 108002670c3fSRiver Riddle 108102670c3fSRiver Riddle return ast::NamedAttributeDecl::create(ctx, name, attrValue); 108202670c3fSRiver Riddle } 108302670c3fSRiver Riddle 10843d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parseLambdaBody( 10853d8b9060SRiver Riddle function_ref<LogicalResult(ast::Stmt *&)> processStatementFn, 10863d8b9060SRiver Riddle bool expectTerminalSemicolon) { 10873d8b9060SRiver Riddle consumeToken(Token::equal_arrow); 10883d8b9060SRiver Riddle 10893d8b9060SRiver Riddle // Parse the single statement of the lambda body. 10903d8b9060SRiver Riddle SMLoc bodyStartLoc = curToken.getStartLoc(); 10913d8b9060SRiver Riddle pushDeclScope(); 10923d8b9060SRiver Riddle FailureOr<ast::Stmt *> singleStatement = parseStmt(expectTerminalSemicolon); 10933d8b9060SRiver Riddle bool failedToParse = 10943d8b9060SRiver Riddle failed(singleStatement) || failed(processStatementFn(*singleStatement)); 10953d8b9060SRiver Riddle popDeclScope(); 10963d8b9060SRiver Riddle if (failedToParse) 10973d8b9060SRiver Riddle return failure(); 10983d8b9060SRiver Riddle 10993d8b9060SRiver Riddle SMRange bodyLoc(bodyStartLoc, curToken.getStartLoc()); 11003d8b9060SRiver Riddle return ast::CompoundStmt::create(ctx, bodyLoc, *singleStatement); 11013d8b9060SRiver Riddle } 11023d8b9060SRiver Riddle 1103faf42264SRiver Riddle FailureOr<ast::VariableDecl *> Parser::parseArgumentDecl() { 1104faf42264SRiver Riddle // Ensure that the argument is named. 1105faf42264SRiver Riddle if (curToken.isNot(Token::identifier) && !curToken.isDependentKeyword()) 1106faf42264SRiver Riddle return emitError("expected identifier argument name"); 1107faf42264SRiver Riddle 1108faf42264SRiver Riddle // Parse the argument similarly to a normal variable. 1109faf42264SRiver Riddle StringRef name = curToken.getSpelling(); 1110faf42264SRiver Riddle SMRange nameLoc = curToken.getLoc(); 1111faf42264SRiver Riddle consumeToken(); 1112faf42264SRiver Riddle 1113faf42264SRiver Riddle if (failed( 1114faf42264SRiver Riddle parseToken(Token::colon, "expected `:` before argument constraint"))) 1115faf42264SRiver Riddle return failure(); 1116faf42264SRiver Riddle 1117faf42264SRiver Riddle FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint(); 1118faf42264SRiver Riddle if (failed(cst)) 1119faf42264SRiver Riddle return failure(); 1120faf42264SRiver Riddle 1121faf42264SRiver Riddle return createArgOrResultVariableDecl(name, nameLoc, *cst); 1122faf42264SRiver Riddle } 1123faf42264SRiver Riddle 1124faf42264SRiver Riddle FailureOr<ast::VariableDecl *> Parser::parseResultDecl(unsigned resultNum) { 1125faf42264SRiver Riddle // Check to see if this result is named. 1126faf42264SRiver Riddle if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) { 1127faf42264SRiver Riddle // Check to see if this name actually refers to a Constraint. 1128b6ec1de7SRiver Riddle if (!curDeclScope->lookup<ast::ConstraintDecl>(curToken.getSpelling())) { 1129faf42264SRiver Riddle // If it wasn't a constraint, parse the result similarly to a variable. If 1130faf42264SRiver Riddle // there is already an existing decl, we will emit an error when defining 1131faf42264SRiver Riddle // this variable later. 1132faf42264SRiver Riddle StringRef name = curToken.getSpelling(); 1133faf42264SRiver Riddle SMRange nameLoc = curToken.getLoc(); 1134faf42264SRiver Riddle consumeToken(); 1135faf42264SRiver Riddle 1136faf42264SRiver Riddle if (failed(parseToken(Token::colon, 1137faf42264SRiver Riddle "expected `:` before result constraint"))) 1138faf42264SRiver Riddle return failure(); 1139faf42264SRiver Riddle 1140faf42264SRiver Riddle FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint(); 1141faf42264SRiver Riddle if (failed(cst)) 1142faf42264SRiver Riddle return failure(); 1143faf42264SRiver Riddle 1144faf42264SRiver Riddle return createArgOrResultVariableDecl(name, nameLoc, *cst); 1145faf42264SRiver Riddle } 1146faf42264SRiver Riddle } 1147faf42264SRiver Riddle 1148faf42264SRiver Riddle // If it isn't named, we parse the constraint directly and create an unnamed 1149faf42264SRiver Riddle // result variable. 1150faf42264SRiver Riddle FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint(); 1151faf42264SRiver Riddle if (failed(cst)) 1152faf42264SRiver Riddle return failure(); 1153faf42264SRiver Riddle 1154faf42264SRiver Riddle return createArgOrResultVariableDecl("", cst->referenceLoc, *cst); 1155faf42264SRiver Riddle } 1156faf42264SRiver Riddle 1157faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> 1158faf42264SRiver Riddle Parser::parseUserConstraintDecl(bool isInline) { 1159faf42264SRiver Riddle // Constraints and rewrites have very similar formats, dispatch to a shared 1160faf42264SRiver Riddle // interface for parsing. 1161faf42264SRiver Riddle return parseUserConstraintOrRewriteDecl<ast::UserConstraintDecl>( 1162ceb5dc55SRiver Riddle [&](auto &&...args) { 1163ceb5dc55SRiver Riddle return this->parseUserPDLLConstraintDecl(args...); 1164ceb5dc55SRiver Riddle }, 1165faf42264SRiver Riddle ParserContext::Constraint, "constraint", isInline); 1166faf42264SRiver Riddle } 1167faf42264SRiver Riddle 1168faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> Parser::parseInlineUserConstraintDecl() { 1169faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> decl = 1170faf42264SRiver Riddle parseUserConstraintDecl(/*isInline=*/true); 1171faf42264SRiver Riddle if (failed(decl) || failed(checkDefineNamedDecl((*decl)->getName()))) 1172faf42264SRiver Riddle return failure(); 1173faf42264SRiver Riddle 1174faf42264SRiver Riddle curDeclScope->add(*decl); 1175faf42264SRiver Riddle return decl; 1176faf42264SRiver Riddle } 1177faf42264SRiver Riddle 1178faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> Parser::parseUserPDLLConstraintDecl( 1179faf42264SRiver Riddle const ast::Name &name, bool isInline, 1180faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope, 1181faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType) { 1182faf42264SRiver Riddle // Push the argument scope back onto the list, so that the body can 1183faf42264SRiver Riddle // reference arguments. 1184faf42264SRiver Riddle pushDeclScope(argumentScope); 1185faf42264SRiver Riddle 1186faf42264SRiver Riddle // Parse the body of the constraint. The body is either defined as a compound 1187faf42264SRiver Riddle // block, i.e. `{ ... }`, or a lambda body, i.e. `=> <expr>`. 1188faf42264SRiver Riddle ast::CompoundStmt *body; 1189faf42264SRiver Riddle if (curToken.is(Token::equal_arrow)) { 1190faf42264SRiver Riddle FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody( 1191faf42264SRiver Riddle [&](ast::Stmt *&stmt) -> LogicalResult { 1192faf42264SRiver Riddle ast::Expr *stmtExpr = dyn_cast<ast::Expr>(stmt); 1193faf42264SRiver Riddle if (!stmtExpr) { 1194faf42264SRiver Riddle return emitError(stmt->getLoc(), 1195faf42264SRiver Riddle "expected `Constraint` lambda body to contain a " 1196faf42264SRiver Riddle "single expression"); 1197faf42264SRiver Riddle } 1198faf42264SRiver Riddle stmt = ast::ReturnStmt::create(ctx, stmt->getLoc(), stmtExpr); 1199faf42264SRiver Riddle return success(); 1200faf42264SRiver Riddle }, 1201faf42264SRiver Riddle /*expectTerminalSemicolon=*/!isInline); 1202faf42264SRiver Riddle if (failed(bodyResult)) 1203faf42264SRiver Riddle return failure(); 1204faf42264SRiver Riddle body = *bodyResult; 1205faf42264SRiver Riddle } else { 1206faf42264SRiver Riddle FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt(); 1207faf42264SRiver Riddle if (failed(bodyResult)) 1208faf42264SRiver Riddle return failure(); 1209faf42264SRiver Riddle body = *bodyResult; 1210faf42264SRiver Riddle 1211faf42264SRiver Riddle // Verify the structure of the body. 1212faf42264SRiver Riddle auto bodyIt = body->begin(), bodyE = body->end(); 1213faf42264SRiver Riddle for (; bodyIt != bodyE; ++bodyIt) 1214faf42264SRiver Riddle if (isa<ast::ReturnStmt>(*bodyIt)) 1215faf42264SRiver Riddle break; 1216faf42264SRiver Riddle if (failed(validateUserConstraintOrRewriteReturn( 1217faf42264SRiver Riddle "Constraint", body, bodyIt, bodyE, results, resultType))) 1218faf42264SRiver Riddle return failure(); 1219faf42264SRiver Riddle } 1220faf42264SRiver Riddle popDeclScope(); 1221faf42264SRiver Riddle 1222faf42264SRiver Riddle return createUserPDLLConstraintOrRewriteDecl<ast::UserConstraintDecl>( 1223faf42264SRiver Riddle name, arguments, results, resultType, body); 1224faf42264SRiver Riddle } 1225faf42264SRiver Riddle 1226faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseUserRewriteDecl(bool isInline) { 1227faf42264SRiver Riddle // Constraints and rewrites have very similar formats, dispatch to a shared 1228faf42264SRiver Riddle // interface for parsing. 1229faf42264SRiver Riddle return parseUserConstraintOrRewriteDecl<ast::UserRewriteDecl>( 1230ceb5dc55SRiver Riddle [&](auto &&...args) { return this->parseUserPDLLRewriteDecl(args...); }, 1231faf42264SRiver Riddle ParserContext::Rewrite, "rewrite", isInline); 1232faf42264SRiver Riddle } 1233faf42264SRiver Riddle 1234faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseInlineUserRewriteDecl() { 1235faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> decl = 1236faf42264SRiver Riddle parseUserRewriteDecl(/*isInline=*/true); 1237faf42264SRiver Riddle if (failed(decl) || failed(checkDefineNamedDecl((*decl)->getName()))) 1238faf42264SRiver Riddle return failure(); 1239faf42264SRiver Riddle 1240faf42264SRiver Riddle curDeclScope->add(*decl); 1241faf42264SRiver Riddle return decl; 1242faf42264SRiver Riddle } 1243faf42264SRiver Riddle 1244faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseUserPDLLRewriteDecl( 1245faf42264SRiver Riddle const ast::Name &name, bool isInline, 1246faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope, 1247faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType) { 1248faf42264SRiver Riddle // Push the argument scope back onto the list, so that the body can 1249faf42264SRiver Riddle // reference arguments. 1250faf42264SRiver Riddle curDeclScope = argumentScope; 1251faf42264SRiver Riddle ast::CompoundStmt *body; 1252faf42264SRiver Riddle if (curToken.is(Token::equal_arrow)) { 1253faf42264SRiver Riddle FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody( 1254faf42264SRiver Riddle [&](ast::Stmt *&statement) -> LogicalResult { 1255faf42264SRiver Riddle if (isa<ast::OpRewriteStmt>(statement)) 1256faf42264SRiver Riddle return success(); 1257faf42264SRiver Riddle 1258faf42264SRiver Riddle ast::Expr *statementExpr = dyn_cast<ast::Expr>(statement); 1259faf42264SRiver Riddle if (!statementExpr) { 1260faf42264SRiver Riddle return emitError( 1261faf42264SRiver Riddle statement->getLoc(), 1262faf42264SRiver Riddle "expected `Rewrite` lambda body to contain a single expression " 1263faf42264SRiver Riddle "or an operation rewrite statement; such as `erase`, " 1264faf42264SRiver Riddle "`replace`, or `rewrite`"); 1265faf42264SRiver Riddle } 1266faf42264SRiver Riddle statement = 1267faf42264SRiver Riddle ast::ReturnStmt::create(ctx, statement->getLoc(), statementExpr); 1268faf42264SRiver Riddle return success(); 1269faf42264SRiver Riddle }, 1270faf42264SRiver Riddle /*expectTerminalSemicolon=*/!isInline); 1271faf42264SRiver Riddle if (failed(bodyResult)) 1272faf42264SRiver Riddle return failure(); 1273faf42264SRiver Riddle body = *bodyResult; 1274faf42264SRiver Riddle } else { 1275faf42264SRiver Riddle FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt(); 1276faf42264SRiver Riddle if (failed(bodyResult)) 1277faf42264SRiver Riddle return failure(); 1278faf42264SRiver Riddle body = *bodyResult; 1279faf42264SRiver Riddle } 1280faf42264SRiver Riddle popDeclScope(); 1281faf42264SRiver Riddle 1282faf42264SRiver Riddle // Verify the structure of the body. 1283faf42264SRiver Riddle auto bodyIt = body->begin(), bodyE = body->end(); 1284faf42264SRiver Riddle for (; bodyIt != bodyE; ++bodyIt) 1285faf42264SRiver Riddle if (isa<ast::ReturnStmt>(*bodyIt)) 1286faf42264SRiver Riddle break; 1287faf42264SRiver Riddle if (failed(validateUserConstraintOrRewriteReturn("Rewrite", body, bodyIt, 1288faf42264SRiver Riddle bodyE, results, resultType))) 1289faf42264SRiver Riddle return failure(); 1290faf42264SRiver Riddle return createUserPDLLConstraintOrRewriteDecl<ast::UserRewriteDecl>( 1291faf42264SRiver Riddle name, arguments, results, resultType, body); 1292faf42264SRiver Riddle } 1293faf42264SRiver Riddle 1294faf42264SRiver Riddle template <typename T, typename ParseUserPDLLDeclFnT> 1295faf42264SRiver Riddle FailureOr<T *> Parser::parseUserConstraintOrRewriteDecl( 1296faf42264SRiver Riddle ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext, 1297faf42264SRiver Riddle StringRef anonymousNamePrefix, bool isInline) { 1298faf42264SRiver Riddle SMRange loc = curToken.getLoc(); 1299faf42264SRiver Riddle consumeToken(); 1300abf0c6c0SJan Svoboda llvm::SaveAndRestore saveCtx(parserContext, declContext); 1301faf42264SRiver Riddle 1302faf42264SRiver Riddle // Parse the name of the decl. 1303faf42264SRiver Riddle const ast::Name *name = nullptr; 1304faf42264SRiver Riddle if (curToken.isNot(Token::identifier)) { 1305faf42264SRiver Riddle // Only inline decls can be un-named. Inline decls are similar to "lambdas" 1306faf42264SRiver Riddle // in C++, so being unnamed is fine. 1307faf42264SRiver Riddle if (!isInline) 1308faf42264SRiver Riddle return emitError("expected identifier name"); 1309faf42264SRiver Riddle 1310faf42264SRiver Riddle // Create a unique anonymous name to use, as the name for this decl is not 1311faf42264SRiver Riddle // important. 1312faf42264SRiver Riddle std::string anonName = 1313faf42264SRiver Riddle llvm::formatv("<anonymous_{0}_{1}>", anonymousNamePrefix, 1314faf42264SRiver Riddle anonymousDeclNameCounter++) 1315faf42264SRiver Riddle .str(); 1316faf42264SRiver Riddle name = &ast::Name::create(ctx, anonName, loc); 1317faf42264SRiver Riddle } else { 1318faf42264SRiver Riddle // If a name was provided, we can use it directly. 1319faf42264SRiver Riddle name = &ast::Name::create(ctx, curToken.getSpelling(), curToken.getLoc()); 1320faf42264SRiver Riddle consumeToken(Token::identifier); 1321faf42264SRiver Riddle } 1322faf42264SRiver Riddle 1323faf42264SRiver Riddle // Parse the functional signature of the decl. 1324faf42264SRiver Riddle SmallVector<ast::VariableDecl *> arguments, results; 1325faf42264SRiver Riddle ast::DeclScope *argumentScope; 1326faf42264SRiver Riddle ast::Type resultType; 1327faf42264SRiver Riddle if (failed(parseUserConstraintOrRewriteSignature(arguments, results, 1328faf42264SRiver Riddle argumentScope, resultType))) 1329faf42264SRiver Riddle return failure(); 1330faf42264SRiver Riddle 1331faf42264SRiver Riddle // Check to see which type of constraint this is. If the constraint contains a 1332faf42264SRiver Riddle // compound body, this is a PDLL decl. 1333faf42264SRiver Riddle if (curToken.isAny(Token::l_brace, Token::equal_arrow)) 1334faf42264SRiver Riddle return parseUserPDLLFn(*name, isInline, arguments, argumentScope, results, 1335faf42264SRiver Riddle resultType); 1336faf42264SRiver Riddle 1337faf42264SRiver Riddle // Otherwise, this is a native decl. 1338faf42264SRiver Riddle return parseUserNativeConstraintOrRewriteDecl<T>(*name, isInline, arguments, 1339faf42264SRiver Riddle results, resultType); 1340faf42264SRiver Riddle } 1341faf42264SRiver Riddle 1342faf42264SRiver Riddle template <typename T> 1343faf42264SRiver Riddle FailureOr<T *> Parser::parseUserNativeConstraintOrRewriteDecl( 1344faf42264SRiver Riddle const ast::Name &name, bool isInline, 1345faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> arguments, 1346faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType) { 1347faf42264SRiver Riddle // If followed by a string, the native code body has also been specified. 1348faf42264SRiver Riddle std::string codeStrStorage; 13490a81ace0SKazu Hirata std::optional<StringRef> optCodeStr; 1350faf42264SRiver Riddle if (curToken.isString()) { 1351faf42264SRiver Riddle codeStrStorage = curToken.getStringValue(); 1352faf42264SRiver Riddle optCodeStr = codeStrStorage; 1353faf42264SRiver Riddle consumeToken(); 1354faf42264SRiver Riddle } else if (isInline) { 1355faf42264SRiver Riddle return emitError(name.getLoc(), 1356faf42264SRiver Riddle "external declarations must be declared in global scope"); 1357ebb1e900SRiver Riddle } else if (curToken.is(Token::error)) { 1358ebb1e900SRiver Riddle return failure(); 1359faf42264SRiver Riddle } 1360faf42264SRiver Riddle if (failed(parseToken(Token::semicolon, 1361faf42264SRiver Riddle "expected `;` after native declaration"))) 1362faf42264SRiver Riddle return failure(); 1363faf42264SRiver Riddle return T::createNative(ctx, name, arguments, results, optCodeStr, resultType); 1364faf42264SRiver Riddle } 1365faf42264SRiver Riddle 1366faf42264SRiver Riddle LogicalResult Parser::parseUserConstraintOrRewriteSignature( 1367faf42264SRiver Riddle SmallVectorImpl<ast::VariableDecl *> &arguments, 1368faf42264SRiver Riddle SmallVectorImpl<ast::VariableDecl *> &results, 1369faf42264SRiver Riddle ast::DeclScope *&argumentScope, ast::Type &resultType) { 1370faf42264SRiver Riddle // Parse the argument list of the decl. 1371faf42264SRiver Riddle if (failed(parseToken(Token::l_paren, "expected `(` to start argument list"))) 1372faf42264SRiver Riddle return failure(); 1373faf42264SRiver Riddle 1374faf42264SRiver Riddle argumentScope = pushDeclScope(); 1375faf42264SRiver Riddle if (curToken.isNot(Token::r_paren)) { 1376faf42264SRiver Riddle do { 1377faf42264SRiver Riddle FailureOr<ast::VariableDecl *> argument = parseArgumentDecl(); 1378faf42264SRiver Riddle if (failed(argument)) 1379faf42264SRiver Riddle return failure(); 1380faf42264SRiver Riddle arguments.emplace_back(*argument); 1381faf42264SRiver Riddle } while (consumeIf(Token::comma)); 1382faf42264SRiver Riddle } 1383faf42264SRiver Riddle popDeclScope(); 1384faf42264SRiver Riddle if (failed(parseToken(Token::r_paren, "expected `)` to end argument list"))) 1385faf42264SRiver Riddle return failure(); 1386faf42264SRiver Riddle 1387faf42264SRiver Riddle // Parse the results of the decl. 1388faf42264SRiver Riddle pushDeclScope(); 1389faf42264SRiver Riddle if (consumeIf(Token::arrow)) { 1390faf42264SRiver Riddle auto parseResultFn = [&]() -> LogicalResult { 1391faf42264SRiver Riddle FailureOr<ast::VariableDecl *> result = parseResultDecl(results.size()); 1392faf42264SRiver Riddle if (failed(result)) 1393faf42264SRiver Riddle return failure(); 1394faf42264SRiver Riddle results.emplace_back(*result); 1395faf42264SRiver Riddle return success(); 1396faf42264SRiver Riddle }; 1397faf42264SRiver Riddle 1398faf42264SRiver Riddle // Check for a list of results. 1399faf42264SRiver Riddle if (consumeIf(Token::l_paren)) { 1400faf42264SRiver Riddle do { 1401faf42264SRiver Riddle if (failed(parseResultFn())) 1402faf42264SRiver Riddle return failure(); 1403faf42264SRiver Riddle } while (consumeIf(Token::comma)); 1404faf42264SRiver Riddle if (failed(parseToken(Token::r_paren, "expected `)` to end result list"))) 1405faf42264SRiver Riddle return failure(); 1406faf42264SRiver Riddle 1407faf42264SRiver Riddle // Otherwise, there is only one result. 1408faf42264SRiver Riddle } else if (failed(parseResultFn())) { 1409faf42264SRiver Riddle return failure(); 1410faf42264SRiver Riddle } 1411faf42264SRiver Riddle } 1412faf42264SRiver Riddle popDeclScope(); 1413faf42264SRiver Riddle 1414faf42264SRiver Riddle // Compute the result type of the decl. 1415faf42264SRiver Riddle resultType = createUserConstraintRewriteResultType(results); 1416faf42264SRiver Riddle 1417faf42264SRiver Riddle // Verify that results are only named if there are more than one. 1418faf42264SRiver Riddle if (results.size() == 1 && !results.front()->getName().getName().empty()) { 1419faf42264SRiver Riddle return emitError( 1420faf42264SRiver Riddle results.front()->getLoc(), 1421faf42264SRiver Riddle "cannot create a single-element tuple with an element label"); 1422faf42264SRiver Riddle } 1423faf42264SRiver Riddle return success(); 1424faf42264SRiver Riddle } 1425faf42264SRiver Riddle 1426faf42264SRiver Riddle LogicalResult Parser::validateUserConstraintOrRewriteReturn( 1427faf42264SRiver Riddle StringRef declType, ast::CompoundStmt *body, 1428faf42264SRiver Riddle ArrayRef<ast::Stmt *>::iterator bodyIt, 1429faf42264SRiver Riddle ArrayRef<ast::Stmt *>::iterator bodyE, 1430faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type &resultType) { 1431faf42264SRiver Riddle // Handle if a `return` was provided. 1432faf42264SRiver Riddle if (bodyIt != bodyE) { 1433faf42264SRiver Riddle // Emit an error if we have trailing statements after the return. 1434faf42264SRiver Riddle if (std::next(bodyIt) != bodyE) { 1435faf42264SRiver Riddle return emitError( 1436faf42264SRiver Riddle (*std::next(bodyIt))->getLoc(), 1437faf42264SRiver Riddle llvm::formatv("`return` terminated the `{0}` body, but found " 1438faf42264SRiver Riddle "trailing statements afterwards", 1439faf42264SRiver Riddle declType)); 1440faf42264SRiver Riddle } 1441faf42264SRiver Riddle 1442faf42264SRiver Riddle // Otherwise if a return wasn't provided, check that no results are 1443faf42264SRiver Riddle // expected. 1444faf42264SRiver Riddle } else if (!results.empty()) { 1445faf42264SRiver Riddle return emitError( 1446faf42264SRiver Riddle {body->getLoc().End, body->getLoc().End}, 1447faf42264SRiver Riddle llvm::formatv("missing return in a `{0}` expected to return `{1}`", 1448faf42264SRiver Riddle declType, resultType)); 1449faf42264SRiver Riddle } 1450faf42264SRiver Riddle return success(); 1451faf42264SRiver Riddle } 1452faf42264SRiver Riddle 14533d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parsePatternLambdaBody() { 14543d8b9060SRiver Riddle return parseLambdaBody([&](ast::Stmt *&statement) -> LogicalResult { 14553d8b9060SRiver Riddle if (isa<ast::OpRewriteStmt>(statement)) 14563d8b9060SRiver Riddle return success(); 14573d8b9060SRiver Riddle return emitError( 14583d8b9060SRiver Riddle statement->getLoc(), 14593d8b9060SRiver Riddle "expected Pattern lambda body to contain a single operation " 14603d8b9060SRiver Riddle "rewrite statement, such as `erase`, `replace`, or `rewrite`"); 14613d8b9060SRiver Riddle }); 14623d8b9060SRiver Riddle } 14633d8b9060SRiver Riddle 146411d26bd1SRiver Riddle FailureOr<ast::Decl *> Parser::parsePatternDecl() { 14656842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 146611d26bd1SRiver Riddle consumeToken(Token::kw_Pattern); 1467abf0c6c0SJan Svoboda llvm::SaveAndRestore saveCtx(parserContext, ParserContext::PatternMatch); 146811d26bd1SRiver Riddle 146911d26bd1SRiver Riddle // Check for an optional identifier for the pattern name. 147011d26bd1SRiver Riddle const ast::Name *name = nullptr; 147111d26bd1SRiver Riddle if (curToken.is(Token::identifier)) { 147211d26bd1SRiver Riddle name = &ast::Name::create(ctx, curToken.getSpelling(), curToken.getLoc()); 147311d26bd1SRiver Riddle consumeToken(Token::identifier); 147411d26bd1SRiver Riddle } 147511d26bd1SRiver Riddle 1476322691abSRiver Riddle // Parse any pattern metadata. 1477322691abSRiver Riddle ParsedPatternMetadata metadata; 1478322691abSRiver Riddle if (consumeIf(Token::kw_with) && failed(parsePatternDeclMetadata(metadata))) 1479322691abSRiver Riddle return failure(); 148011d26bd1SRiver Riddle 148111d26bd1SRiver Riddle // Parse the pattern body. 148211d26bd1SRiver Riddle ast::CompoundStmt *body; 148311d26bd1SRiver Riddle 14843d8b9060SRiver Riddle // Handle a lambda body. 14853d8b9060SRiver Riddle if (curToken.is(Token::equal_arrow)) { 14863d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> bodyResult = parsePatternLambdaBody(); 14873d8b9060SRiver Riddle if (failed(bodyResult)) 14883d8b9060SRiver Riddle return failure(); 14893d8b9060SRiver Riddle body = *bodyResult; 14903d8b9060SRiver Riddle } else { 149111d26bd1SRiver Riddle if (curToken.isNot(Token::l_brace)) 14923d8b9060SRiver Riddle return emitError("expected `{` or `=>` to start pattern body"); 149311d26bd1SRiver Riddle FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt(); 149411d26bd1SRiver Riddle if (failed(bodyResult)) 149511d26bd1SRiver Riddle return failure(); 149611d26bd1SRiver Riddle body = *bodyResult; 149711d26bd1SRiver Riddle 149811d26bd1SRiver Riddle // Verify the body of the pattern. 149911d26bd1SRiver Riddle auto bodyIt = body->begin(), bodyE = body->end(); 150011d26bd1SRiver Riddle for (; bodyIt != bodyE; ++bodyIt) { 1501faf42264SRiver Riddle if (isa<ast::ReturnStmt>(*bodyIt)) { 1502faf42264SRiver Riddle return emitError((*bodyIt)->getLoc(), 1503faf42264SRiver Riddle "`return` statements are only permitted within a " 1504faf42264SRiver Riddle "`Constraint` or `Rewrite` body"); 1505faf42264SRiver Riddle } 150611d26bd1SRiver Riddle // Break when we've found the rewrite statement. 150711d26bd1SRiver Riddle if (isa<ast::OpRewriteStmt>(*bodyIt)) 150811d26bd1SRiver Riddle break; 150911d26bd1SRiver Riddle } 151011d26bd1SRiver Riddle if (bodyIt == bodyE) { 151111d26bd1SRiver Riddle return emitError(loc, 151211d26bd1SRiver Riddle "expected Pattern body to terminate with an operation " 151311d26bd1SRiver Riddle "rewrite statement, such as `erase`"); 151411d26bd1SRiver Riddle } 151511d26bd1SRiver Riddle if (std::next(bodyIt) != bodyE) { 151611d26bd1SRiver Riddle return emitError((*std::next(bodyIt))->getLoc(), 151711d26bd1SRiver Riddle "Pattern body was terminated by an operation " 151811d26bd1SRiver Riddle "rewrite statement, but found trailing statements"); 151911d26bd1SRiver Riddle } 15203d8b9060SRiver Riddle } 152111d26bd1SRiver Riddle 1522322691abSRiver Riddle return createPatternDecl(loc, name, metadata, body); 1523322691abSRiver Riddle } 1524322691abSRiver Riddle 1525322691abSRiver Riddle LogicalResult 1526322691abSRiver Riddle Parser::parsePatternDeclMetadata(ParsedPatternMetadata &metadata) { 15270a81ace0SKazu Hirata std::optional<SMRange> benefitLoc; 15280a81ace0SKazu Hirata std::optional<SMRange> hasBoundedRecursionLoc; 1529322691abSRiver Riddle 1530322691abSRiver Riddle do { 1531008de486SRiver Riddle // Handle metadata code completion. 1532008de486SRiver Riddle if (curToken.is(Token::code_complete)) 1533008de486SRiver Riddle return codeCompletePatternMetadata(); 1534008de486SRiver Riddle 1535322691abSRiver Riddle if (curToken.isNot(Token::identifier)) 1536322691abSRiver Riddle return emitError("expected pattern metadata identifier"); 1537322691abSRiver Riddle StringRef metadataStr = curToken.getSpelling(); 15386842ec42SRiver Riddle SMRange metadataLoc = curToken.getLoc(); 1539322691abSRiver Riddle consumeToken(Token::identifier); 1540322691abSRiver Riddle 1541322691abSRiver Riddle // Parse the benefit metadata: benefit(<integer-value>) 1542322691abSRiver Riddle if (metadataStr == "benefit") { 1543322691abSRiver Riddle if (benefitLoc) { 1544322691abSRiver Riddle return emitErrorAndNote(metadataLoc, 1545322691abSRiver Riddle "pattern benefit has already been specified", 1546322691abSRiver Riddle *benefitLoc, "see previous definition here"); 1547322691abSRiver Riddle } 1548322691abSRiver Riddle if (failed(parseToken(Token::l_paren, 1549322691abSRiver Riddle "expected `(` before pattern benefit"))) 1550322691abSRiver Riddle return failure(); 1551322691abSRiver Riddle 1552322691abSRiver Riddle uint16_t benefitValue = 0; 1553322691abSRiver Riddle if (curToken.isNot(Token::integer)) 1554322691abSRiver Riddle return emitError("expected integral pattern benefit"); 1555322691abSRiver Riddle if (curToken.getSpelling().getAsInteger(/*Radix=*/10, benefitValue)) 1556322691abSRiver Riddle return emitError( 1557322691abSRiver Riddle "expected pattern benefit to fit within a 16-bit integer"); 1558322691abSRiver Riddle consumeToken(Token::integer); 1559322691abSRiver Riddle 1560322691abSRiver Riddle metadata.benefit = benefitValue; 1561322691abSRiver Riddle benefitLoc = metadataLoc; 1562322691abSRiver Riddle 1563322691abSRiver Riddle if (failed( 1564322691abSRiver Riddle parseToken(Token::r_paren, "expected `)` after pattern benefit"))) 1565322691abSRiver Riddle return failure(); 1566322691abSRiver Riddle continue; 1567322691abSRiver Riddle } 1568322691abSRiver Riddle 1569322691abSRiver Riddle // Parse the bounded recursion metadata: recursion 1570322691abSRiver Riddle if (metadataStr == "recursion") { 1571322691abSRiver Riddle if (hasBoundedRecursionLoc) { 1572322691abSRiver Riddle return emitErrorAndNote( 1573322691abSRiver Riddle metadataLoc, 1574322691abSRiver Riddle "pattern recursion metadata has already been specified", 1575322691abSRiver Riddle *hasBoundedRecursionLoc, "see previous definition here"); 1576322691abSRiver Riddle } 1577322691abSRiver Riddle metadata.hasBoundedRecursion = true; 1578322691abSRiver Riddle hasBoundedRecursionLoc = metadataLoc; 1579322691abSRiver Riddle continue; 1580322691abSRiver Riddle } 1581322691abSRiver Riddle 1582322691abSRiver Riddle return emitError(metadataLoc, "unknown pattern metadata"); 1583322691abSRiver Riddle } while (consumeIf(Token::comma)); 1584322691abSRiver Riddle 1585322691abSRiver Riddle return success(); 158611d26bd1SRiver Riddle } 158711d26bd1SRiver Riddle 158811d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseTypeConstraintExpr() { 158911d26bd1SRiver Riddle consumeToken(Token::less); 159011d26bd1SRiver Riddle 159111d26bd1SRiver Riddle FailureOr<ast::Expr *> typeExpr = parseExpr(); 159211d26bd1SRiver Riddle if (failed(typeExpr) || 159311d26bd1SRiver Riddle failed(parseToken(Token::greater, 159411d26bd1SRiver Riddle "expected `>` after variable type constraint"))) 159511d26bd1SRiver Riddle return failure(); 159611d26bd1SRiver Riddle return typeExpr; 159711d26bd1SRiver Riddle } 159811d26bd1SRiver Riddle 159911d26bd1SRiver Riddle LogicalResult Parser::checkDefineNamedDecl(const ast::Name &name) { 160011d26bd1SRiver Riddle assert(curDeclScope && "defining decl outside of a decl scope"); 160111d26bd1SRiver Riddle if (ast::Decl *lastDecl = curDeclScope->lookup(name.getName())) { 160211d26bd1SRiver Riddle return emitErrorAndNote( 160311d26bd1SRiver Riddle name.getLoc(), "`" + name.getName() + "` has already been defined", 160411d26bd1SRiver Riddle lastDecl->getName()->getLoc(), "see previous definition here"); 160511d26bd1SRiver Riddle } 160611d26bd1SRiver Riddle return success(); 160711d26bd1SRiver Riddle } 160811d26bd1SRiver Riddle 160911d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> 1610faf42264SRiver Riddle Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type, 1611faf42264SRiver Riddle ast::Expr *initExpr, 161211d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints) { 161311d26bd1SRiver Riddle assert(curDeclScope && "defining variable outside of decl scope"); 161411d26bd1SRiver Riddle const ast::Name &nameDecl = ast::Name::create(ctx, name, nameLoc); 161511d26bd1SRiver Riddle 161611d26bd1SRiver Riddle // If the name of the variable indicates a special variable, we don't add it 161711d26bd1SRiver Riddle // to the scope. This variable is local to the definition point. 161811d26bd1SRiver Riddle if (name.empty() || name == "_") { 161911d26bd1SRiver Riddle return ast::VariableDecl::create(ctx, nameDecl, type, initExpr, 162011d26bd1SRiver Riddle constraints); 162111d26bd1SRiver Riddle } 162211d26bd1SRiver Riddle if (failed(checkDefineNamedDecl(nameDecl))) 162311d26bd1SRiver Riddle return failure(); 162411d26bd1SRiver Riddle 162511d26bd1SRiver Riddle auto *varDecl = 162611d26bd1SRiver Riddle ast::VariableDecl::create(ctx, nameDecl, type, initExpr, constraints); 162711d26bd1SRiver Riddle curDeclScope->add(varDecl); 162811d26bd1SRiver Riddle return varDecl; 162911d26bd1SRiver Riddle } 163011d26bd1SRiver Riddle 163111d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> 1632faf42264SRiver Riddle Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type, 163311d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints) { 163411d26bd1SRiver Riddle return defineVariableDecl(name, nameLoc, type, /*initExpr=*/nullptr, 163511d26bd1SRiver Riddle constraints); 163611d26bd1SRiver Riddle } 163711d26bd1SRiver Riddle 163811d26bd1SRiver Riddle LogicalResult Parser::parseVariableDeclConstraintList( 163911d26bd1SRiver Riddle SmallVectorImpl<ast::ConstraintRef> &constraints) { 16400a81ace0SKazu Hirata std::optional<SMRange> typeConstraint; 164111d26bd1SRiver Riddle auto parseSingleConstraint = [&] { 1642faf42264SRiver Riddle FailureOr<ast::ConstraintRef> constraint = parseConstraint( 1643b6ec1de7SRiver Riddle typeConstraint, constraints, /*allowInlineTypeConstraints=*/true); 164411d26bd1SRiver Riddle if (failed(constraint)) 164511d26bd1SRiver Riddle return failure(); 164611d26bd1SRiver Riddle constraints.push_back(*constraint); 164711d26bd1SRiver Riddle return success(); 164811d26bd1SRiver Riddle }; 164911d26bd1SRiver Riddle 165011d26bd1SRiver Riddle // Check to see if this is a single constraint, or a list. 165111d26bd1SRiver Riddle if (!consumeIf(Token::l_square)) 165211d26bd1SRiver Riddle return parseSingleConstraint(); 165311d26bd1SRiver Riddle 165411d26bd1SRiver Riddle do { 165511d26bd1SRiver Riddle if (failed(parseSingleConstraint())) 165611d26bd1SRiver Riddle return failure(); 165711d26bd1SRiver Riddle } while (consumeIf(Token::comma)); 165811d26bd1SRiver Riddle return parseToken(Token::r_square, "expected `]` after constraint list"); 165911d26bd1SRiver Riddle } 166011d26bd1SRiver Riddle 166111d26bd1SRiver Riddle FailureOr<ast::ConstraintRef> 16620a81ace0SKazu Hirata Parser::parseConstraint(std::optional<SMRange> &typeConstraint, 1663faf42264SRiver Riddle ArrayRef<ast::ConstraintRef> existingConstraints, 1664b6ec1de7SRiver Riddle bool allowInlineTypeConstraints) { 166511d26bd1SRiver Riddle auto parseTypeConstraint = [&](ast::Expr *&typeExpr) -> LogicalResult { 1666faf42264SRiver Riddle if (!allowInlineTypeConstraints) { 1667faf42264SRiver Riddle return emitError( 1668faf42264SRiver Riddle curToken.getLoc(), 1669faf42264SRiver Riddle "inline `Attr`, `Value`, and `ValueRange` type constraints are not " 1670faf42264SRiver Riddle "permitted on arguments or results"); 1671faf42264SRiver Riddle } 167211d26bd1SRiver Riddle if (typeConstraint) 167311d26bd1SRiver Riddle return emitErrorAndNote( 167411d26bd1SRiver Riddle curToken.getLoc(), 167511d26bd1SRiver Riddle "the type of this variable has already been constrained", 167611d26bd1SRiver Riddle *typeConstraint, "see previous constraint location here"); 167711d26bd1SRiver Riddle FailureOr<ast::Expr *> constraintExpr = parseTypeConstraintExpr(); 167811d26bd1SRiver Riddle if (failed(constraintExpr)) 167911d26bd1SRiver Riddle return failure(); 168011d26bd1SRiver Riddle typeExpr = *constraintExpr; 168111d26bd1SRiver Riddle typeConstraint = typeExpr->getLoc(); 168211d26bd1SRiver Riddle return success(); 168311d26bd1SRiver Riddle }; 168411d26bd1SRiver Riddle 16856842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 168611d26bd1SRiver Riddle switch (curToken.getKind()) { 168711d26bd1SRiver Riddle case Token::kw_Attr: { 168811d26bd1SRiver Riddle consumeToken(Token::kw_Attr); 168911d26bd1SRiver Riddle 169011d26bd1SRiver Riddle // Check for a type constraint. 169111d26bd1SRiver Riddle ast::Expr *typeExpr = nullptr; 169211d26bd1SRiver Riddle if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr))) 169311d26bd1SRiver Riddle return failure(); 169411d26bd1SRiver Riddle return ast::ConstraintRef( 169511d26bd1SRiver Riddle ast::AttrConstraintDecl::create(ctx, loc, typeExpr), loc); 169611d26bd1SRiver Riddle } 169711d26bd1SRiver Riddle case Token::kw_Op: { 169811d26bd1SRiver Riddle consumeToken(Token::kw_Op); 169911d26bd1SRiver Riddle 170012eebb8eSRiver Riddle // Parse an optional operation name. If the name isn't provided, this refers 170112eebb8eSRiver Riddle // to "any" operation. 170212eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> opName = 170312eebb8eSRiver Riddle parseWrappedOperationName(/*allowEmptyName=*/true); 170411d26bd1SRiver Riddle if (failed(opName)) 170511d26bd1SRiver Riddle return failure(); 170611d26bd1SRiver Riddle 170711d26bd1SRiver Riddle return ast::ConstraintRef(ast::OpConstraintDecl::create(ctx, loc, *opName), 170811d26bd1SRiver Riddle loc); 170911d26bd1SRiver Riddle } 171011d26bd1SRiver Riddle case Token::kw_Type: 171111d26bd1SRiver Riddle consumeToken(Token::kw_Type); 171211d26bd1SRiver Riddle return ast::ConstraintRef(ast::TypeConstraintDecl::create(ctx, loc), loc); 171311d26bd1SRiver Riddle case Token::kw_TypeRange: 171411d26bd1SRiver Riddle consumeToken(Token::kw_TypeRange); 171511d26bd1SRiver Riddle return ast::ConstraintRef(ast::TypeRangeConstraintDecl::create(ctx, loc), 171611d26bd1SRiver Riddle loc); 171711d26bd1SRiver Riddle case Token::kw_Value: { 171811d26bd1SRiver Riddle consumeToken(Token::kw_Value); 171911d26bd1SRiver Riddle 172011d26bd1SRiver Riddle // Check for a type constraint. 172111d26bd1SRiver Riddle ast::Expr *typeExpr = nullptr; 172211d26bd1SRiver Riddle if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr))) 172311d26bd1SRiver Riddle return failure(); 172411d26bd1SRiver Riddle 172511d26bd1SRiver Riddle return ast::ConstraintRef( 172611d26bd1SRiver Riddle ast::ValueConstraintDecl::create(ctx, loc, typeExpr), loc); 172711d26bd1SRiver Riddle } 172811d26bd1SRiver Riddle case Token::kw_ValueRange: { 172911d26bd1SRiver Riddle consumeToken(Token::kw_ValueRange); 173011d26bd1SRiver Riddle 173111d26bd1SRiver Riddle // Check for a type constraint. 173211d26bd1SRiver Riddle ast::Expr *typeExpr = nullptr; 173311d26bd1SRiver Riddle if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr))) 173411d26bd1SRiver Riddle return failure(); 173511d26bd1SRiver Riddle 173611d26bd1SRiver Riddle return ast::ConstraintRef( 173711d26bd1SRiver Riddle ast::ValueRangeConstraintDecl::create(ctx, loc, typeExpr), loc); 173811d26bd1SRiver Riddle } 1739faf42264SRiver Riddle 1740faf42264SRiver Riddle case Token::kw_Constraint: { 1741faf42264SRiver Riddle // Handle an inline constraint. 1742faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl(); 1743faf42264SRiver Riddle if (failed(decl)) 1744faf42264SRiver Riddle return failure(); 1745faf42264SRiver Riddle return ast::ConstraintRef(*decl, loc); 1746faf42264SRiver Riddle } 174711d26bd1SRiver Riddle case Token::identifier: { 174811d26bd1SRiver Riddle StringRef constraintName = curToken.getSpelling(); 174911d26bd1SRiver Riddle consumeToken(Token::identifier); 175011d26bd1SRiver Riddle 175111d26bd1SRiver Riddle // Lookup the referenced constraint. 175211d26bd1SRiver Riddle ast::Decl *cstDecl = curDeclScope->lookup<ast::Decl>(constraintName); 175311d26bd1SRiver Riddle if (!cstDecl) { 175411d26bd1SRiver Riddle return emitError(loc, "unknown reference to constraint `" + 175511d26bd1SRiver Riddle constraintName + "`"); 175611d26bd1SRiver Riddle } 175711d26bd1SRiver Riddle 175811d26bd1SRiver Riddle // Handle a reference to a proper constraint. 175911d26bd1SRiver Riddle if (auto *cst = dyn_cast<ast::ConstraintDecl>(cstDecl)) 176011d26bd1SRiver Riddle return ast::ConstraintRef(cst, loc); 176111d26bd1SRiver Riddle 176211d26bd1SRiver Riddle return emitErrorAndNote( 176311d26bd1SRiver Riddle loc, "invalid reference to non-constraint", cstDecl->getLoc(), 176411d26bd1SRiver Riddle "see the definition of `" + constraintName + "` here"); 176511d26bd1SRiver Riddle } 1766008de486SRiver Riddle // Handle single entity constraint code completion. 1767008de486SRiver Riddle case Token::code_complete: { 1768008de486SRiver Riddle // Try to infer the current type for use by code completion. 1769008de486SRiver Riddle ast::Type inferredType; 1770b6ec1de7SRiver Riddle if (failed(validateVariableConstraints(existingConstraints, inferredType))) 1771008de486SRiver Riddle return failure(); 1772008de486SRiver Riddle 1773b6ec1de7SRiver Riddle return codeCompleteConstraintName(inferredType, allowInlineTypeConstraints); 1774008de486SRiver Riddle } 177511d26bd1SRiver Riddle default: 177611d26bd1SRiver Riddle break; 177711d26bd1SRiver Riddle } 177811d26bd1SRiver Riddle return emitError(loc, "expected identifier constraint"); 177911d26bd1SRiver Riddle } 178011d26bd1SRiver Riddle 1781faf42264SRiver Riddle FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() { 17820a81ace0SKazu Hirata std::optional<SMRange> typeConstraint; 17831a36588eSKazu Hirata return parseConstraint(typeConstraint, /*existingConstraints=*/std::nullopt, 1784b6ec1de7SRiver Riddle /*allowInlineTypeConstraints=*/false); 1785faf42264SRiver Riddle } 1786faf42264SRiver Riddle 178711d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 178811d26bd1SRiver Riddle // Exprs 178911d26bd1SRiver Riddle 179011d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseExpr() { 179111d26bd1SRiver Riddle if (curToken.is(Token::underscore)) 179211d26bd1SRiver Riddle return parseUnderscoreExpr(); 179311d26bd1SRiver Riddle 179411d26bd1SRiver Riddle // Parse the LHS expression. 179511d26bd1SRiver Riddle FailureOr<ast::Expr *> lhsExpr; 179611d26bd1SRiver Riddle switch (curToken.getKind()) { 1797d7e7fdf3SRiver Riddle case Token::kw_attr: 1798d7e7fdf3SRiver Riddle lhsExpr = parseAttributeExpr(); 1799d7e7fdf3SRiver Riddle break; 1800faf42264SRiver Riddle case Token::kw_Constraint: 1801faf42264SRiver Riddle lhsExpr = parseInlineConstraintLambdaExpr(); 1802faf42264SRiver Riddle break; 1803930916c7SMogball case Token::kw_not: 1804930916c7SMogball lhsExpr = parseNegatedExpr(); 1805930916c7SMogball break; 180611d26bd1SRiver Riddle case Token::identifier: 180711d26bd1SRiver Riddle lhsExpr = parseIdentifierExpr(); 180811d26bd1SRiver Riddle break; 180902670c3fSRiver Riddle case Token::kw_op: 181002670c3fSRiver Riddle lhsExpr = parseOperationExpr(); 181102670c3fSRiver Riddle break; 1812faf42264SRiver Riddle case Token::kw_Rewrite: 1813faf42264SRiver Riddle lhsExpr = parseInlineRewriteLambdaExpr(); 1814faf42264SRiver Riddle break; 1815d7e7fdf3SRiver Riddle case Token::kw_type: 1816d7e7fdf3SRiver Riddle lhsExpr = parseTypeExpr(); 1817d7e7fdf3SRiver Riddle break; 1818f62a57a3SRiver Riddle case Token::l_paren: 1819f62a57a3SRiver Riddle lhsExpr = parseTupleExpr(); 1820f62a57a3SRiver Riddle break; 182111d26bd1SRiver Riddle default: 182211d26bd1SRiver Riddle return emitError("expected expression"); 182311d26bd1SRiver Riddle } 182411d26bd1SRiver Riddle if (failed(lhsExpr)) 182511d26bd1SRiver Riddle return failure(); 182611d26bd1SRiver Riddle 182711d26bd1SRiver Riddle // Check for an operator expression. 182811d26bd1SRiver Riddle while (true) { 182911d26bd1SRiver Riddle switch (curToken.getKind()) { 183011d26bd1SRiver Riddle case Token::dot: 183111d26bd1SRiver Riddle lhsExpr = parseMemberAccessExpr(*lhsExpr); 183211d26bd1SRiver Riddle break; 1833faf42264SRiver Riddle case Token::l_paren: 1834faf42264SRiver Riddle lhsExpr = parseCallExpr(*lhsExpr); 1835faf42264SRiver Riddle break; 183611d26bd1SRiver Riddle default: 183711d26bd1SRiver Riddle return lhsExpr; 183811d26bd1SRiver Riddle } 183911d26bd1SRiver Riddle if (failed(lhsExpr)) 184011d26bd1SRiver Riddle return failure(); 184111d26bd1SRiver Riddle } 184211d26bd1SRiver Riddle } 184311d26bd1SRiver Riddle 1844d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> Parser::parseAttributeExpr() { 18456842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 1846d7e7fdf3SRiver Riddle consumeToken(Token::kw_attr); 1847d7e7fdf3SRiver Riddle 1848d7e7fdf3SRiver Riddle // If we aren't followed by a `<`, the `attr` keyword is treated as a normal 1849d7e7fdf3SRiver Riddle // identifier. 1850d7e7fdf3SRiver Riddle if (!consumeIf(Token::less)) { 1851d7e7fdf3SRiver Riddle resetToken(loc); 1852d7e7fdf3SRiver Riddle return parseIdentifierExpr(); 1853d7e7fdf3SRiver Riddle } 1854d7e7fdf3SRiver Riddle 1855d7e7fdf3SRiver Riddle if (!curToken.isString()) 1856d7e7fdf3SRiver Riddle return emitError("expected string literal containing MLIR attribute"); 1857d7e7fdf3SRiver Riddle std::string attrExpr = curToken.getStringValue(); 1858d7e7fdf3SRiver Riddle consumeToken(); 1859d7e7fdf3SRiver Riddle 18606d4471efSRiver Riddle loc.End = curToken.getEndLoc(); 1861d7e7fdf3SRiver Riddle if (failed( 1862d7e7fdf3SRiver Riddle parseToken(Token::greater, "expected `>` after attribute literal"))) 1863d7e7fdf3SRiver Riddle return failure(); 1864d7e7fdf3SRiver Riddle return ast::AttributeExpr::create(ctx, loc, attrExpr); 1865d7e7fdf3SRiver Riddle } 1866d7e7fdf3SRiver Riddle 1867930916c7SMogball FailureOr<ast::Expr *> Parser::parseCallExpr(ast::Expr *parentExpr, 1868930916c7SMogball bool isNegated) { 1869faf42264SRiver Riddle consumeToken(Token::l_paren); 1870faf42264SRiver Riddle 1871faf42264SRiver Riddle // Parse the arguments of the call. 1872faf42264SRiver Riddle SmallVector<ast::Expr *> arguments; 1873faf42264SRiver Riddle if (curToken.isNot(Token::r_paren)) { 1874faf42264SRiver Riddle do { 1875469c5894SRiver Riddle // Handle code completion for the call arguments. 1876469c5894SRiver Riddle if (curToken.is(Token::code_complete)) { 1877469c5894SRiver Riddle codeCompleteCallSignature(parentExpr, arguments.size()); 1878469c5894SRiver Riddle return failure(); 1879469c5894SRiver Riddle } 1880469c5894SRiver Riddle 1881faf42264SRiver Riddle FailureOr<ast::Expr *> argument = parseExpr(); 1882faf42264SRiver Riddle if (failed(argument)) 1883faf42264SRiver Riddle return failure(); 1884faf42264SRiver Riddle arguments.push_back(*argument); 1885faf42264SRiver Riddle } while (consumeIf(Token::comma)); 1886faf42264SRiver Riddle } 18876d4471efSRiver Riddle 18886d4471efSRiver Riddle SMRange loc(parentExpr->getLoc().Start, curToken.getEndLoc()); 1889faf42264SRiver Riddle if (failed(parseToken(Token::r_paren, "expected `)` after argument list"))) 1890faf42264SRiver Riddle return failure(); 1891faf42264SRiver Riddle 1892930916c7SMogball return createCallExpr(loc, parentExpr, arguments, isNegated); 1893faf42264SRiver Riddle } 1894faf42264SRiver Riddle 1895faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) { 189611d26bd1SRiver Riddle ast::Decl *decl = curDeclScope->lookup(name); 189711d26bd1SRiver Riddle if (!decl) 189811d26bd1SRiver Riddle return emitError(loc, "undefined reference to `" + name + "`"); 189911d26bd1SRiver Riddle 190011d26bd1SRiver Riddle return createDeclRefExpr(loc, decl); 190111d26bd1SRiver Riddle } 190211d26bd1SRiver Riddle 190311d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseIdentifierExpr() { 190411d26bd1SRiver Riddle StringRef name = curToken.getSpelling(); 19056842ec42SRiver Riddle SMRange nameLoc = curToken.getLoc(); 190611d26bd1SRiver Riddle consumeToken(); 190711d26bd1SRiver Riddle 190811d26bd1SRiver Riddle // Check to see if this is a decl ref expression that defines a variable 190911d26bd1SRiver Riddle // inline. 191011d26bd1SRiver Riddle if (consumeIf(Token::colon)) { 191111d26bd1SRiver Riddle SmallVector<ast::ConstraintRef> constraints; 191211d26bd1SRiver Riddle if (failed(parseVariableDeclConstraintList(constraints))) 191311d26bd1SRiver Riddle return failure(); 191411d26bd1SRiver Riddle ast::Type type; 191511d26bd1SRiver Riddle if (failed(validateVariableConstraints(constraints, type))) 191611d26bd1SRiver Riddle return failure(); 191711d26bd1SRiver Riddle return createInlineVariableExpr(type, name, nameLoc, constraints); 191811d26bd1SRiver Riddle } 191911d26bd1SRiver Riddle 192011d26bd1SRiver Riddle return parseDeclRefExpr(name, nameLoc); 192111d26bd1SRiver Riddle } 192211d26bd1SRiver Riddle 1923faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseInlineConstraintLambdaExpr() { 1924faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl(); 1925faf42264SRiver Riddle if (failed(decl)) 1926faf42264SRiver Riddle return failure(); 1927faf42264SRiver Riddle 1928faf42264SRiver Riddle return ast::DeclRefExpr::create(ctx, (*decl)->getLoc(), *decl, 1929faf42264SRiver Riddle ast::ConstraintType::get(ctx)); 1930faf42264SRiver Riddle } 1931faf42264SRiver Riddle 1932faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseInlineRewriteLambdaExpr() { 1933faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> decl = parseInlineUserRewriteDecl(); 1934faf42264SRiver Riddle if (failed(decl)) 1935faf42264SRiver Riddle return failure(); 1936faf42264SRiver Riddle 1937faf42264SRiver Riddle return ast::DeclRefExpr::create(ctx, (*decl)->getLoc(), *decl, 1938faf42264SRiver Riddle ast::RewriteType::get(ctx)); 1939faf42264SRiver Riddle } 1940faf42264SRiver Riddle 194111d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseMemberAccessExpr(ast::Expr *parentExpr) { 19426d4471efSRiver Riddle SMRange dotLoc = curToken.getLoc(); 194311d26bd1SRiver Riddle consumeToken(Token::dot); 194411d26bd1SRiver Riddle 1945008de486SRiver Riddle // Check for code completion of the member name. 1946008de486SRiver Riddle if (curToken.is(Token::code_complete)) 1947008de486SRiver Riddle return codeCompleteMemberAccess(parentExpr); 1948008de486SRiver Riddle 194911d26bd1SRiver Riddle // Parse the member name. 195011d26bd1SRiver Riddle Token memberNameTok = curToken; 195111d26bd1SRiver Riddle if (memberNameTok.isNot(Token::identifier, Token::integer) && 195211d26bd1SRiver Riddle !memberNameTok.isKeyword()) 19536d4471efSRiver Riddle return emitError(dotLoc, "expected identifier or numeric member name"); 195411d26bd1SRiver Riddle StringRef memberName = memberNameTok.getSpelling(); 19556d4471efSRiver Riddle SMRange loc(parentExpr->getLoc().Start, curToken.getEndLoc()); 195611d26bd1SRiver Riddle consumeToken(); 195711d26bd1SRiver Riddle 195811d26bd1SRiver Riddle return createMemberAccessExpr(parentExpr, memberName, loc); 195911d26bd1SRiver Riddle } 196011d26bd1SRiver Riddle 1961930916c7SMogball FailureOr<ast::Expr *> Parser::parseNegatedExpr() { 1962930916c7SMogball consumeToken(Token::kw_not); 1963930916c7SMogball // Only native constraints are supported after negation 1964930916c7SMogball if (!curToken.is(Token::identifier)) 1965930916c7SMogball return emitError("expected native constraint"); 1966930916c7SMogball FailureOr<ast::Expr *> identifierExpr = parseIdentifierExpr(); 1967930916c7SMogball if (failed(identifierExpr)) 1968930916c7SMogball return failure(); 1969780a2098SMatthias Gehre if (!curToken.is(Token::l_paren)) 1970780a2098SMatthias Gehre return emitError("expected `(` after function name"); 1971930916c7SMogball return parseCallExpr(*identifierExpr, /*isNegated = */ true); 1972930916c7SMogball } 1973930916c7SMogball 197412eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> Parser::parseOperationName(bool allowEmptyName) { 19756842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 197611d26bd1SRiver Riddle 1977008de486SRiver Riddle // Check for code completion for the dialect name. 1978008de486SRiver Riddle if (curToken.is(Token::code_complete)) 1979008de486SRiver Riddle return codeCompleteDialectName(); 1980008de486SRiver Riddle 198111d26bd1SRiver Riddle // Handle the case of an no operation name. 198212eebb8eSRiver Riddle if (curToken.isNot(Token::identifier) && !curToken.isKeyword()) { 198312eebb8eSRiver Riddle if (allowEmptyName) 19846842ec42SRiver Riddle return ast::OpNameDecl::create(ctx, SMRange()); 198512eebb8eSRiver Riddle return emitError("expected dialect namespace"); 198612eebb8eSRiver Riddle } 198711d26bd1SRiver Riddle StringRef name = curToken.getSpelling(); 198811d26bd1SRiver Riddle consumeToken(); 198911d26bd1SRiver Riddle 199011d26bd1SRiver Riddle // Otherwise, this is a literal operation name. 199111d26bd1SRiver Riddle if (failed(parseToken(Token::dot, "expected `.` after dialect namespace"))) 199211d26bd1SRiver Riddle return failure(); 199311d26bd1SRiver Riddle 1994008de486SRiver Riddle // Check for code completion for the operation name. 1995008de486SRiver Riddle if (curToken.is(Token::code_complete)) 1996008de486SRiver Riddle return codeCompleteOperationName(name); 1997008de486SRiver Riddle 199811d26bd1SRiver Riddle if (curToken.isNot(Token::identifier) && !curToken.isKeyword()) 199911d26bd1SRiver Riddle return emitError("expected operation name after dialect namespace"); 200011d26bd1SRiver Riddle 200111d26bd1SRiver Riddle name = StringRef(name.data(), name.size() + 1); 200211d26bd1SRiver Riddle do { 200311d26bd1SRiver Riddle name = StringRef(name.data(), name.size() + curToken.getSpelling().size()); 200411d26bd1SRiver Riddle loc.End = curToken.getEndLoc(); 200511d26bd1SRiver Riddle consumeToken(); 200611d26bd1SRiver Riddle } while (curToken.isAny(Token::identifier, Token::dot) || 200711d26bd1SRiver Riddle curToken.isKeyword()); 200811d26bd1SRiver Riddle return ast::OpNameDecl::create(ctx, ast::Name::create(ctx, name, loc)); 200911d26bd1SRiver Riddle } 201011d26bd1SRiver Riddle 201112eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> 201212eebb8eSRiver Riddle Parser::parseWrappedOperationName(bool allowEmptyName) { 201311d26bd1SRiver Riddle if (!consumeIf(Token::less)) 20146842ec42SRiver Riddle return ast::OpNameDecl::create(ctx, SMRange()); 201511d26bd1SRiver Riddle 201612eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> opNameDecl = parseOperationName(allowEmptyName); 201711d26bd1SRiver Riddle if (failed(opNameDecl)) 201811d26bd1SRiver Riddle return failure(); 201911d26bd1SRiver Riddle 202011d26bd1SRiver Riddle if (failed(parseToken(Token::greater, "expected `>` after operation name"))) 202111d26bd1SRiver Riddle return failure(); 202211d26bd1SRiver Riddle return opNameDecl; 202311d26bd1SRiver Riddle } 202411d26bd1SRiver Riddle 202591b8d96fSRiver Riddle FailureOr<ast::Expr *> 202691b8d96fSRiver Riddle Parser::parseOperationExpr(OpResultTypeContext inputResultTypeContext) { 20276842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 202802670c3fSRiver Riddle consumeToken(Token::kw_op); 202902670c3fSRiver Riddle 203002670c3fSRiver Riddle // If it isn't followed by a `<`, the `op` keyword is treated as a normal 203102670c3fSRiver Riddle // identifier. 203202670c3fSRiver Riddle if (curToken.isNot(Token::less)) { 203302670c3fSRiver Riddle resetToken(loc); 203402670c3fSRiver Riddle return parseIdentifierExpr(); 203502670c3fSRiver Riddle } 203602670c3fSRiver Riddle 203702670c3fSRiver Riddle // Parse the operation name. The name may be elided, in which case the 203802670c3fSRiver Riddle // operation refers to "any" operation(i.e. a difference between `MyOp` and 203912eebb8eSRiver Riddle // `Operation*`). Operation names within a rewrite context must be named. 204012eebb8eSRiver Riddle bool allowEmptyName = parserContext != ParserContext::Rewrite; 204112eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> opNameDecl = 204212eebb8eSRiver Riddle parseWrappedOperationName(allowEmptyName); 204302670c3fSRiver Riddle if (failed(opNameDecl)) 204402670c3fSRiver Riddle return failure(); 20450a81ace0SKazu Hirata std::optional<StringRef> opName = (*opNameDecl)->getName(); 204602670c3fSRiver Riddle 2047a486cf5eSRiver Riddle // Functor used to create an implicit range variable, used for implicit "all" 2048a486cf5eSRiver Riddle // operand or results variables. 2049a486cf5eSRiver Riddle auto createImplicitRangeVar = [&](ast::ConstraintDecl *cst, ast::Type type) { 2050a486cf5eSRiver Riddle FailureOr<ast::VariableDecl *> rangeVar = 2051a486cf5eSRiver Riddle defineVariableDecl("_", loc, type, ast::ConstraintRef(cst, loc)); 2052a486cf5eSRiver Riddle assert(succeeded(rangeVar) && "expected range variable to be valid"); 2053a486cf5eSRiver Riddle return ast::DeclRefExpr::create(ctx, loc, *rangeVar, type); 2054a486cf5eSRiver Riddle }; 2055a486cf5eSRiver Riddle 205602670c3fSRiver Riddle // Check for the optional list of operands. 205702670c3fSRiver Riddle SmallVector<ast::Expr *> operands; 2058a486cf5eSRiver Riddle if (!consumeIf(Token::l_paren)) { 2059a486cf5eSRiver Riddle // If the operand list isn't specified and we are in a match context, define 2060a486cf5eSRiver Riddle // an inplace unconstrained operand range corresponding to all of the 2061a486cf5eSRiver Riddle // operands of the operation. This avoids treating zero operands the same 2062a486cf5eSRiver Riddle // way as "unconstrained operands". 2063a486cf5eSRiver Riddle if (parserContext != ParserContext::Rewrite) { 2064a486cf5eSRiver Riddle operands.push_back(createImplicitRangeVar( 2065a486cf5eSRiver Riddle ast::ValueRangeConstraintDecl::create(ctx, loc), valueRangeTy)); 2066a486cf5eSRiver Riddle } 2067a486cf5eSRiver Riddle } else if (!consumeIf(Token::r_paren)) { 20680429472eSRiver Riddle // If the operand list was specified and non-empty, parse the operands. 20690429472eSRiver Riddle do { 2070469c5894SRiver Riddle // Check for operand signature code completion. 2071469c5894SRiver Riddle if (curToken.is(Token::code_complete)) { 2072469c5894SRiver Riddle codeCompleteOperationOperandsSignature(opName, operands.size()); 2073469c5894SRiver Riddle return failure(); 2074469c5894SRiver Riddle } 2075469c5894SRiver Riddle 207602670c3fSRiver Riddle FailureOr<ast::Expr *> operand = parseExpr(); 207702670c3fSRiver Riddle if (failed(operand)) 207802670c3fSRiver Riddle return failure(); 207902670c3fSRiver Riddle operands.push_back(*operand); 208002670c3fSRiver Riddle } while (consumeIf(Token::comma)); 208102670c3fSRiver Riddle 208202670c3fSRiver Riddle if (failed(parseToken(Token::r_paren, 208302670c3fSRiver Riddle "expected `)` after operation operand list"))) 208402670c3fSRiver Riddle return failure(); 208502670c3fSRiver Riddle } 208602670c3fSRiver Riddle 208702670c3fSRiver Riddle // Check for the optional list of attributes. 208802670c3fSRiver Riddle SmallVector<ast::NamedAttributeDecl *> attributes; 208902670c3fSRiver Riddle if (consumeIf(Token::l_brace)) { 209002670c3fSRiver Riddle do { 2091008de486SRiver Riddle FailureOr<ast::NamedAttributeDecl *> decl = 2092008de486SRiver Riddle parseNamedAttributeDecl(opName); 209302670c3fSRiver Riddle if (failed(decl)) 209402670c3fSRiver Riddle return failure(); 209502670c3fSRiver Riddle attributes.emplace_back(*decl); 209602670c3fSRiver Riddle } while (consumeIf(Token::comma)); 209702670c3fSRiver Riddle 209802670c3fSRiver Riddle if (failed(parseToken(Token::r_brace, 209902670c3fSRiver Riddle "expected `}` after operation attribute list"))) 210002670c3fSRiver Riddle return failure(); 210102670c3fSRiver Riddle } 210202670c3fSRiver Riddle 210391b8d96fSRiver Riddle // Handle the result types of the operation. 210402670c3fSRiver Riddle SmallVector<ast::Expr *> resultTypes; 210591b8d96fSRiver Riddle OpResultTypeContext resultTypeContext = inputResultTypeContext; 210691b8d96fSRiver Riddle 210791b8d96fSRiver Riddle // Check for an explicit list of result types. 210802670c3fSRiver Riddle if (consumeIf(Token::arrow)) { 210902670c3fSRiver Riddle if (failed(parseToken(Token::l_paren, 211002670c3fSRiver Riddle "expected `(` before operation result type list"))) 211102670c3fSRiver Riddle return failure(); 211202670c3fSRiver Riddle 211391b8d96fSRiver Riddle // If result types are provided, initially assume that the operation does 211491b8d96fSRiver Riddle // not rely on type inferrence. We don't assert that it isn't, because we 211591b8d96fSRiver Riddle // may be inferring the value of some type/type range variables, but given 211691b8d96fSRiver Riddle // that these variables may be defined in calls we can't always discern when 211791b8d96fSRiver Riddle // this is the case. 211891b8d96fSRiver Riddle resultTypeContext = OpResultTypeContext::Explicit; 211991b8d96fSRiver Riddle 2120a486cf5eSRiver Riddle // Handle the case of an empty result list. 2121a486cf5eSRiver Riddle if (!consumeIf(Token::r_paren)) { 212202670c3fSRiver Riddle do { 2123469c5894SRiver Riddle // Check for result signature code completion. 2124469c5894SRiver Riddle if (curToken.is(Token::code_complete)) { 2125469c5894SRiver Riddle codeCompleteOperationResultsSignature(opName, resultTypes.size()); 2126469c5894SRiver Riddle return failure(); 2127469c5894SRiver Riddle } 2128469c5894SRiver Riddle 212902670c3fSRiver Riddle FailureOr<ast::Expr *> resultTypeExpr = parseExpr(); 213002670c3fSRiver Riddle if (failed(resultTypeExpr)) 213102670c3fSRiver Riddle return failure(); 213202670c3fSRiver Riddle resultTypes.push_back(*resultTypeExpr); 213302670c3fSRiver Riddle } while (consumeIf(Token::comma)); 213402670c3fSRiver Riddle 213502670c3fSRiver Riddle if (failed(parseToken(Token::r_paren, 213602670c3fSRiver Riddle "expected `)` after operation result type list"))) 213702670c3fSRiver Riddle return failure(); 213802670c3fSRiver Riddle } 2139a486cf5eSRiver Riddle } else if (parserContext != ParserContext::Rewrite) { 2140a486cf5eSRiver Riddle // If the result list isn't specified and we are in a match context, define 2141a486cf5eSRiver Riddle // an inplace unconstrained result range corresponding to all of the results 2142a486cf5eSRiver Riddle // of the operation. This avoids treating zero results the same way as 2143a486cf5eSRiver Riddle // "unconstrained results". 2144a486cf5eSRiver Riddle resultTypes.push_back(createImplicitRangeVar( 2145a486cf5eSRiver Riddle ast::TypeRangeConstraintDecl::create(ctx, loc), typeRangeTy)); 214691b8d96fSRiver Riddle } else if (resultTypeContext == OpResultTypeContext::Explicit) { 214791b8d96fSRiver Riddle // If the result list isn't specified and we are in a rewrite, try to infer 214891b8d96fSRiver Riddle // them at runtime instead. 214991b8d96fSRiver Riddle resultTypeContext = OpResultTypeContext::Interface; 2150a486cf5eSRiver Riddle } 215102670c3fSRiver Riddle 215291b8d96fSRiver Riddle return createOperationExpr(loc, *opNameDecl, resultTypeContext, operands, 215391b8d96fSRiver Riddle attributes, resultTypes); 215402670c3fSRiver Riddle } 215502670c3fSRiver Riddle 2156f62a57a3SRiver Riddle FailureOr<ast::Expr *> Parser::parseTupleExpr() { 21576842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 2158f62a57a3SRiver Riddle consumeToken(Token::l_paren); 2159f62a57a3SRiver Riddle 21606842ec42SRiver Riddle DenseMap<StringRef, SMRange> usedNames; 2161f62a57a3SRiver Riddle SmallVector<StringRef> elementNames; 2162f62a57a3SRiver Riddle SmallVector<ast::Expr *> elements; 2163f62a57a3SRiver Riddle if (curToken.isNot(Token::r_paren)) { 2164f62a57a3SRiver Riddle do { 2165f62a57a3SRiver Riddle // Check for the optional element name assignment before the value. 2166f62a57a3SRiver Riddle StringRef elementName; 2167f62a57a3SRiver Riddle if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) { 2168f62a57a3SRiver Riddle Token elementNameTok = curToken; 2169f62a57a3SRiver Riddle consumeToken(); 2170f62a57a3SRiver Riddle 2171f62a57a3SRiver Riddle // The element name is only present if followed by an `=`. 2172f62a57a3SRiver Riddle if (consumeIf(Token::equal)) { 2173f62a57a3SRiver Riddle elementName = elementNameTok.getSpelling(); 2174f62a57a3SRiver Riddle 2175f62a57a3SRiver Riddle // Check to see if this name is already used. 2176f62a57a3SRiver Riddle auto elementNameIt = 2177f62a57a3SRiver Riddle usedNames.try_emplace(elementName, elementNameTok.getLoc()); 2178f62a57a3SRiver Riddle if (!elementNameIt.second) { 2179f62a57a3SRiver Riddle return emitErrorAndNote( 2180f62a57a3SRiver Riddle elementNameTok.getLoc(), 2181f62a57a3SRiver Riddle llvm::formatv("duplicate tuple element label `{0}`", 2182f62a57a3SRiver Riddle elementName), 2183f62a57a3SRiver Riddle elementNameIt.first->getSecond(), 2184f62a57a3SRiver Riddle "see previous label use here"); 2185f62a57a3SRiver Riddle } 2186f62a57a3SRiver Riddle } else { 2187f62a57a3SRiver Riddle // Otherwise, we treat this as part of an expression so reset the 2188f62a57a3SRiver Riddle // lexer. 2189f62a57a3SRiver Riddle resetToken(elementNameTok.getLoc()); 2190f62a57a3SRiver Riddle } 2191f62a57a3SRiver Riddle } 2192f62a57a3SRiver Riddle elementNames.push_back(elementName); 2193f62a57a3SRiver Riddle 2194f62a57a3SRiver Riddle // Parse the tuple element value. 2195f62a57a3SRiver Riddle FailureOr<ast::Expr *> element = parseExpr(); 2196f62a57a3SRiver Riddle if (failed(element)) 2197f62a57a3SRiver Riddle return failure(); 2198f62a57a3SRiver Riddle elements.push_back(*element); 2199f62a57a3SRiver Riddle } while (consumeIf(Token::comma)); 2200f62a57a3SRiver Riddle } 2201f62a57a3SRiver Riddle loc.End = curToken.getEndLoc(); 2202f62a57a3SRiver Riddle if (failed( 2203f62a57a3SRiver Riddle parseToken(Token::r_paren, "expected `)` after tuple element list"))) 2204f62a57a3SRiver Riddle return failure(); 2205f62a57a3SRiver Riddle return createTupleExpr(loc, elements, elementNames); 2206f62a57a3SRiver Riddle } 2207f62a57a3SRiver Riddle 2208d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> Parser::parseTypeExpr() { 22096842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 2210d7e7fdf3SRiver Riddle consumeToken(Token::kw_type); 2211d7e7fdf3SRiver Riddle 2212d7e7fdf3SRiver Riddle // If we aren't followed by a `<`, the `type` keyword is treated as a normal 2213d7e7fdf3SRiver Riddle // identifier. 2214d7e7fdf3SRiver Riddle if (!consumeIf(Token::less)) { 2215d7e7fdf3SRiver Riddle resetToken(loc); 2216d7e7fdf3SRiver Riddle return parseIdentifierExpr(); 2217d7e7fdf3SRiver Riddle } 2218d7e7fdf3SRiver Riddle 2219d7e7fdf3SRiver Riddle if (!curToken.isString()) 2220d7e7fdf3SRiver Riddle return emitError("expected string literal containing MLIR type"); 2221d7e7fdf3SRiver Riddle std::string attrExpr = curToken.getStringValue(); 2222d7e7fdf3SRiver Riddle consumeToken(); 2223d7e7fdf3SRiver Riddle 22246d4471efSRiver Riddle loc.End = curToken.getEndLoc(); 2225d7e7fdf3SRiver Riddle if (failed(parseToken(Token::greater, "expected `>` after type literal"))) 2226d7e7fdf3SRiver Riddle return failure(); 2227d7e7fdf3SRiver Riddle return ast::TypeExpr::create(ctx, loc, attrExpr); 2228d7e7fdf3SRiver Riddle } 2229d7e7fdf3SRiver Riddle 223011d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseUnderscoreExpr() { 223111d26bd1SRiver Riddle StringRef name = curToken.getSpelling(); 22326842ec42SRiver Riddle SMRange nameLoc = curToken.getLoc(); 223311d26bd1SRiver Riddle consumeToken(Token::underscore); 223411d26bd1SRiver Riddle 223511d26bd1SRiver Riddle // Underscore expressions require a constraint list. 223611d26bd1SRiver Riddle if (failed(parseToken(Token::colon, "expected `:` after `_` variable"))) 223711d26bd1SRiver Riddle return failure(); 223811d26bd1SRiver Riddle 223911d26bd1SRiver Riddle // Parse the constraints for the expression. 224011d26bd1SRiver Riddle SmallVector<ast::ConstraintRef> constraints; 224111d26bd1SRiver Riddle if (failed(parseVariableDeclConstraintList(constraints))) 224211d26bd1SRiver Riddle return failure(); 224311d26bd1SRiver Riddle 224411d26bd1SRiver Riddle ast::Type type; 224511d26bd1SRiver Riddle if (failed(validateVariableConstraints(constraints, type))) 224611d26bd1SRiver Riddle return failure(); 224711d26bd1SRiver Riddle return createInlineVariableExpr(type, name, nameLoc, constraints); 224811d26bd1SRiver Riddle } 224911d26bd1SRiver Riddle 225011d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 225111d26bd1SRiver Riddle // Stmts 225211d26bd1SRiver Riddle 225311d26bd1SRiver Riddle FailureOr<ast::Stmt *> Parser::parseStmt(bool expectTerminalSemicolon) { 225411d26bd1SRiver Riddle FailureOr<ast::Stmt *> stmt; 225511d26bd1SRiver Riddle switch (curToken.getKind()) { 225611d26bd1SRiver Riddle case Token::kw_erase: 225711d26bd1SRiver Riddle stmt = parseEraseStmt(); 225811d26bd1SRiver Riddle break; 225911d26bd1SRiver Riddle case Token::kw_let: 226011d26bd1SRiver Riddle stmt = parseLetStmt(); 226111d26bd1SRiver Riddle break; 226212eebb8eSRiver Riddle case Token::kw_replace: 226312eebb8eSRiver Riddle stmt = parseReplaceStmt(); 226412eebb8eSRiver Riddle break; 2265faf42264SRiver Riddle case Token::kw_return: 2266faf42264SRiver Riddle stmt = parseReturnStmt(); 2267faf42264SRiver Riddle break; 22683ee44cb7SRiver Riddle case Token::kw_rewrite: 22693ee44cb7SRiver Riddle stmt = parseRewriteStmt(); 22703ee44cb7SRiver Riddle break; 227111d26bd1SRiver Riddle default: 227211d26bd1SRiver Riddle stmt = parseExpr(); 227311d26bd1SRiver Riddle break; 227411d26bd1SRiver Riddle } 227511d26bd1SRiver Riddle if (failed(stmt) || 227611d26bd1SRiver Riddle (expectTerminalSemicolon && 227711d26bd1SRiver Riddle failed(parseToken(Token::semicolon, "expected `;` after statement")))) 227811d26bd1SRiver Riddle return failure(); 227911d26bd1SRiver Riddle return stmt; 228011d26bd1SRiver Riddle } 228111d26bd1SRiver Riddle 228211d26bd1SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parseCompoundStmt() { 22836842ec42SRiver Riddle SMLoc startLoc = curToken.getStartLoc(); 228411d26bd1SRiver Riddle consumeToken(Token::l_brace); 228511d26bd1SRiver Riddle 228611d26bd1SRiver Riddle // Push a new block scope and parse any nested statements. 228711d26bd1SRiver Riddle pushDeclScope(); 228811d26bd1SRiver Riddle SmallVector<ast::Stmt *> statements; 228911d26bd1SRiver Riddle while (curToken.isNot(Token::r_brace)) { 229011d26bd1SRiver Riddle FailureOr<ast::Stmt *> statement = parseStmt(); 229111d26bd1SRiver Riddle if (failed(statement)) 229211d26bd1SRiver Riddle return popDeclScope(), failure(); 229311d26bd1SRiver Riddle statements.push_back(*statement); 229411d26bd1SRiver Riddle } 229511d26bd1SRiver Riddle popDeclScope(); 229611d26bd1SRiver Riddle 229711d26bd1SRiver Riddle // Consume the end brace. 22986842ec42SRiver Riddle SMRange location(startLoc, curToken.getEndLoc()); 229911d26bd1SRiver Riddle consumeToken(Token::r_brace); 230011d26bd1SRiver Riddle 230111d26bd1SRiver Riddle return ast::CompoundStmt::create(ctx, location, statements); 230211d26bd1SRiver Riddle } 230311d26bd1SRiver Riddle 230411d26bd1SRiver Riddle FailureOr<ast::EraseStmt *> Parser::parseEraseStmt() { 2305faf42264SRiver Riddle if (parserContext == ParserContext::Constraint) 2306faf42264SRiver Riddle return emitError("`erase` cannot be used within a Constraint"); 23076842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 230811d26bd1SRiver Riddle consumeToken(Token::kw_erase); 230911d26bd1SRiver Riddle 231011d26bd1SRiver Riddle // Parse the root operation expression. 231111d26bd1SRiver Riddle FailureOr<ast::Expr *> rootOp = parseExpr(); 231211d26bd1SRiver Riddle if (failed(rootOp)) 231311d26bd1SRiver Riddle return failure(); 231411d26bd1SRiver Riddle 231511d26bd1SRiver Riddle return createEraseStmt(loc, *rootOp); 231611d26bd1SRiver Riddle } 231711d26bd1SRiver Riddle 231811d26bd1SRiver Riddle FailureOr<ast::LetStmt *> Parser::parseLetStmt() { 23196842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 232011d26bd1SRiver Riddle consumeToken(Token::kw_let); 232111d26bd1SRiver Riddle 232211d26bd1SRiver Riddle // Parse the name of the new variable. 23236842ec42SRiver Riddle SMRange varLoc = curToken.getLoc(); 232411d26bd1SRiver Riddle if (curToken.isNot(Token::identifier) && !curToken.isDependentKeyword()) { 232511d26bd1SRiver Riddle // `_` is a reserved variable name. 232611d26bd1SRiver Riddle if (curToken.is(Token::underscore)) { 232711d26bd1SRiver Riddle return emitError(varLoc, 232811d26bd1SRiver Riddle "`_` may only be used to define \"inline\" variables"); 232911d26bd1SRiver Riddle } 233011d26bd1SRiver Riddle return emitError(varLoc, 233111d26bd1SRiver Riddle "expected identifier after `let` to name a new variable"); 233211d26bd1SRiver Riddle } 233311d26bd1SRiver Riddle StringRef varName = curToken.getSpelling(); 233411d26bd1SRiver Riddle consumeToken(); 233511d26bd1SRiver Riddle 233611d26bd1SRiver Riddle // Parse the optional set of constraints. 233711d26bd1SRiver Riddle SmallVector<ast::ConstraintRef> constraints; 233811d26bd1SRiver Riddle if (consumeIf(Token::colon) && 233911d26bd1SRiver Riddle failed(parseVariableDeclConstraintList(constraints))) 234011d26bd1SRiver Riddle return failure(); 234111d26bd1SRiver Riddle 234211d26bd1SRiver Riddle // Parse the optional initializer expression. 234311d26bd1SRiver Riddle ast::Expr *initializer = nullptr; 234411d26bd1SRiver Riddle if (consumeIf(Token::equal)) { 234511d26bd1SRiver Riddle FailureOr<ast::Expr *> initOrFailure = parseExpr(); 234611d26bd1SRiver Riddle if (failed(initOrFailure)) 234711d26bd1SRiver Riddle return failure(); 234811d26bd1SRiver Riddle initializer = *initOrFailure; 234911d26bd1SRiver Riddle 235011d26bd1SRiver Riddle // Check that the constraints are compatible with having an initializer, 235111d26bd1SRiver Riddle // e.g. type constraints cannot be used with initializers. 235211d26bd1SRiver Riddle for (ast::ConstraintRef constraint : constraints) { 235311d26bd1SRiver Riddle LogicalResult result = 235411d26bd1SRiver Riddle TypeSwitch<const ast::Node *, LogicalResult>(constraint.constraint) 235511d26bd1SRiver Riddle .Case<ast::AttrConstraintDecl, ast::ValueConstraintDecl, 235611d26bd1SRiver Riddle ast::ValueRangeConstraintDecl>([&](const auto *cst) { 23570a0aff2dSMikhail Goncharov if (cst->getTypeExpr()) { 2358e76043acSRiver Riddle return this->emitError( 235911d26bd1SRiver Riddle constraint.referenceLoc, 236011d26bd1SRiver Riddle "type constraints are not permitted on variables with " 236111d26bd1SRiver Riddle "initializers"); 236211d26bd1SRiver Riddle } 236311d26bd1SRiver Riddle return success(); 236411d26bd1SRiver Riddle }) 236511d26bd1SRiver Riddle .Default(success()); 236611d26bd1SRiver Riddle if (failed(result)) 236711d26bd1SRiver Riddle return failure(); 236811d26bd1SRiver Riddle } 236911d26bd1SRiver Riddle } 237011d26bd1SRiver Riddle 237111d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> varDecl = 237211d26bd1SRiver Riddle createVariableDecl(varName, varLoc, initializer, constraints); 237311d26bd1SRiver Riddle if (failed(varDecl)) 237411d26bd1SRiver Riddle return failure(); 237511d26bd1SRiver Riddle return ast::LetStmt::create(ctx, loc, *varDecl); 237611d26bd1SRiver Riddle } 237711d26bd1SRiver Riddle 237812eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *> Parser::parseReplaceStmt() { 2379faf42264SRiver Riddle if (parserContext == ParserContext::Constraint) 2380faf42264SRiver Riddle return emitError("`replace` cannot be used within a Constraint"); 23816842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 238212eebb8eSRiver Riddle consumeToken(Token::kw_replace); 238312eebb8eSRiver Riddle 238412eebb8eSRiver Riddle // Parse the root operation expression. 238512eebb8eSRiver Riddle FailureOr<ast::Expr *> rootOp = parseExpr(); 238612eebb8eSRiver Riddle if (failed(rootOp)) 238712eebb8eSRiver Riddle return failure(); 238812eebb8eSRiver Riddle 238912eebb8eSRiver Riddle if (failed( 239012eebb8eSRiver Riddle parseToken(Token::kw_with, "expected `with` after root operation"))) 239112eebb8eSRiver Riddle return failure(); 239212eebb8eSRiver Riddle 239312eebb8eSRiver Riddle // The replacement portion of this statement is within a rewrite context. 2394abf0c6c0SJan Svoboda llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite); 239512eebb8eSRiver Riddle 239612eebb8eSRiver Riddle // Parse the replacement values. 239712eebb8eSRiver Riddle SmallVector<ast::Expr *> replValues; 239812eebb8eSRiver Riddle if (consumeIf(Token::l_paren)) { 239912eebb8eSRiver Riddle if (consumeIf(Token::r_paren)) { 240012eebb8eSRiver Riddle return emitError( 240112eebb8eSRiver Riddle loc, "expected at least one replacement value, consider using " 240212eebb8eSRiver Riddle "`erase` if no replacement values are desired"); 240312eebb8eSRiver Riddle } 240412eebb8eSRiver Riddle 240512eebb8eSRiver Riddle do { 240612eebb8eSRiver Riddle FailureOr<ast::Expr *> replExpr = parseExpr(); 240712eebb8eSRiver Riddle if (failed(replExpr)) 240812eebb8eSRiver Riddle return failure(); 240912eebb8eSRiver Riddle replValues.emplace_back(*replExpr); 241012eebb8eSRiver Riddle } while (consumeIf(Token::comma)); 241112eebb8eSRiver Riddle 241212eebb8eSRiver Riddle if (failed(parseToken(Token::r_paren, 241312eebb8eSRiver Riddle "expected `)` after replacement values"))) 241412eebb8eSRiver Riddle return failure(); 241512eebb8eSRiver Riddle } else { 241691b8d96fSRiver Riddle // Handle replacement with an operation uniquely, as the replacement 241791b8d96fSRiver Riddle // operation supports type inferrence from the root operation. 241891b8d96fSRiver Riddle FailureOr<ast::Expr *> replExpr; 241991b8d96fSRiver Riddle if (curToken.is(Token::kw_op)) 242091b8d96fSRiver Riddle replExpr = parseOperationExpr(OpResultTypeContext::Replacement); 242191b8d96fSRiver Riddle else 242291b8d96fSRiver Riddle replExpr = parseExpr(); 242312eebb8eSRiver Riddle if (failed(replExpr)) 242412eebb8eSRiver Riddle return failure(); 242512eebb8eSRiver Riddle replValues.emplace_back(*replExpr); 242612eebb8eSRiver Riddle } 242712eebb8eSRiver Riddle 242812eebb8eSRiver Riddle return createReplaceStmt(loc, *rootOp, replValues); 242912eebb8eSRiver Riddle } 243012eebb8eSRiver Riddle 2431faf42264SRiver Riddle FailureOr<ast::ReturnStmt *> Parser::parseReturnStmt() { 2432faf42264SRiver Riddle SMRange loc = curToken.getLoc(); 2433faf42264SRiver Riddle consumeToken(Token::kw_return); 2434faf42264SRiver Riddle 2435faf42264SRiver Riddle // Parse the result value. 2436faf42264SRiver Riddle FailureOr<ast::Expr *> resultExpr = parseExpr(); 2437faf42264SRiver Riddle if (failed(resultExpr)) 2438faf42264SRiver Riddle return failure(); 2439faf42264SRiver Riddle 2440faf42264SRiver Riddle return ast::ReturnStmt::create(ctx, loc, *resultExpr); 2441faf42264SRiver Riddle } 2442faf42264SRiver Riddle 24433ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *> Parser::parseRewriteStmt() { 2444faf42264SRiver Riddle if (parserContext == ParserContext::Constraint) 2445faf42264SRiver Riddle return emitError("`rewrite` cannot be used within a Constraint"); 24466842ec42SRiver Riddle SMRange loc = curToken.getLoc(); 24473ee44cb7SRiver Riddle consumeToken(Token::kw_rewrite); 24483ee44cb7SRiver Riddle 24493ee44cb7SRiver Riddle // Parse the root operation. 24503ee44cb7SRiver Riddle FailureOr<ast::Expr *> rootOp = parseExpr(); 24513ee44cb7SRiver Riddle if (failed(rootOp)) 24523ee44cb7SRiver Riddle return failure(); 24533ee44cb7SRiver Riddle 24543ee44cb7SRiver Riddle if (failed(parseToken(Token::kw_with, "expected `with` before rewrite body"))) 24553ee44cb7SRiver Riddle return failure(); 24563ee44cb7SRiver Riddle 24573ee44cb7SRiver Riddle if (curToken.isNot(Token::l_brace)) 24583ee44cb7SRiver Riddle return emitError("expected `{` to start rewrite body"); 24593ee44cb7SRiver Riddle 24603ee44cb7SRiver Riddle // The rewrite body of this statement is within a rewrite context. 2461abf0c6c0SJan Svoboda llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite); 24623ee44cb7SRiver Riddle 24633ee44cb7SRiver Riddle FailureOr<ast::CompoundStmt *> rewriteBody = parseCompoundStmt(); 24643ee44cb7SRiver Riddle if (failed(rewriteBody)) 24653ee44cb7SRiver Riddle return failure(); 24663ee44cb7SRiver Riddle 2467faf42264SRiver Riddle // Verify the rewrite body. 2468faf42264SRiver Riddle for (const ast::Stmt *stmt : (*rewriteBody)->getChildren()) { 2469faf42264SRiver Riddle if (isa<ast::ReturnStmt>(stmt)) { 2470faf42264SRiver Riddle return emitError(stmt->getLoc(), 2471faf42264SRiver Riddle "`return` statements are only permitted within a " 2472faf42264SRiver Riddle "`Constraint` or `Rewrite` body"); 2473faf42264SRiver Riddle } 2474faf42264SRiver Riddle } 2475faf42264SRiver Riddle 24763ee44cb7SRiver Riddle return createRewriteStmt(loc, *rootOp, *rewriteBody); 24773ee44cb7SRiver Riddle } 24783ee44cb7SRiver Riddle 247911d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 248011d26bd1SRiver Riddle // Creation+Analysis 248111d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 248211d26bd1SRiver Riddle 248311d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 248411d26bd1SRiver Riddle // Decls 248511d26bd1SRiver Riddle 2486faf42264SRiver Riddle ast::CallableDecl *Parser::tryExtractCallableDecl(ast::Node *node) { 2487faf42264SRiver Riddle // Unwrap reference expressions. 2488faf42264SRiver Riddle if (auto *init = dyn_cast<ast::DeclRefExpr>(node)) 2489faf42264SRiver Riddle node = init->getDecl(); 2490faf42264SRiver Riddle return dyn_cast<ast::CallableDecl>(node); 2491faf42264SRiver Riddle } 2492faf42264SRiver Riddle 249311d26bd1SRiver Riddle FailureOr<ast::PatternDecl *> 24946842ec42SRiver Riddle Parser::createPatternDecl(SMRange loc, const ast::Name *name, 2495322691abSRiver Riddle const ParsedPatternMetadata &metadata, 249611d26bd1SRiver Riddle ast::CompoundStmt *body) { 2497322691abSRiver Riddle return ast::PatternDecl::create(ctx, loc, name, metadata.benefit, 2498322691abSRiver Riddle metadata.hasBoundedRecursion, body); 249911d26bd1SRiver Riddle } 250011d26bd1SRiver Riddle 2501faf42264SRiver Riddle ast::Type Parser::createUserConstraintRewriteResultType( 2502faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results) { 2503faf42264SRiver Riddle // Single result decls use the type of the single result. 2504faf42264SRiver Riddle if (results.size() == 1) 2505faf42264SRiver Riddle return results[0]->getType(); 2506faf42264SRiver Riddle 2507faf42264SRiver Riddle // Multiple results use a tuple type, with the types and names grabbed from 2508faf42264SRiver Riddle // the result variable decls. 2509faf42264SRiver Riddle auto resultTypes = llvm::map_range( 2510faf42264SRiver Riddle results, [&](const auto *result) { return result->getType(); }); 2511faf42264SRiver Riddle auto resultNames = llvm::map_range( 2512faf42264SRiver Riddle results, [&](const auto *result) { return result->getName().getName(); }); 2513faf42264SRiver Riddle return ast::TupleType::get(ctx, llvm::to_vector(resultTypes), 2514faf42264SRiver Riddle llvm::to_vector(resultNames)); 2515faf42264SRiver Riddle } 2516faf42264SRiver Riddle 2517faf42264SRiver Riddle template <typename T> 2518faf42264SRiver Riddle FailureOr<T *> Parser::createUserPDLLConstraintOrRewriteDecl( 2519faf42264SRiver Riddle const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments, 2520faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> results, ast::Type resultType, 2521faf42264SRiver Riddle ast::CompoundStmt *body) { 2522faf42264SRiver Riddle if (!body->getChildren().empty()) { 2523faf42264SRiver Riddle if (auto *retStmt = dyn_cast<ast::ReturnStmt>(body->getChildren().back())) { 2524faf42264SRiver Riddle ast::Expr *resultExpr = retStmt->getResultExpr(); 2525faf42264SRiver Riddle 2526faf42264SRiver Riddle // Process the result of the decl. If no explicit signature results 2527faf42264SRiver Riddle // were provided, check for return type inference. Otherwise, check that 2528faf42264SRiver Riddle // the return expression can be converted to the expected type. 2529faf42264SRiver Riddle if (results.empty()) 2530faf42264SRiver Riddle resultType = resultExpr->getType(); 2531faf42264SRiver Riddle else if (failed(convertExpressionTo(resultExpr, resultType))) 2532faf42264SRiver Riddle return failure(); 2533faf42264SRiver Riddle else 2534faf42264SRiver Riddle retStmt->setResultExpr(resultExpr); 2535faf42264SRiver Riddle } 2536faf42264SRiver Riddle } 2537faf42264SRiver Riddle return T::createPDLL(ctx, name, arguments, results, body, resultType); 2538faf42264SRiver Riddle } 2539faf42264SRiver Riddle 254011d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> 2541faf42264SRiver Riddle Parser::createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer, 254211d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints) { 254311d26bd1SRiver Riddle // The type of the variable, which is expected to be inferred by either a 254411d26bd1SRiver Riddle // constraint or an initializer expression. 254511d26bd1SRiver Riddle ast::Type type; 254611d26bd1SRiver Riddle if (failed(validateVariableConstraints(constraints, type))) 254711d26bd1SRiver Riddle return failure(); 254811d26bd1SRiver Riddle 254911d26bd1SRiver Riddle if (initializer) { 255011d26bd1SRiver Riddle // Update the variable type based on the initializer, or try to convert the 255111d26bd1SRiver Riddle // initializer to the existing type. 255211d26bd1SRiver Riddle if (!type) 255311d26bd1SRiver Riddle type = initializer->getType(); 255411d26bd1SRiver Riddle else if (ast::Type mergedType = type.refineWith(initializer->getType())) 255511d26bd1SRiver Riddle type = mergedType; 255611d26bd1SRiver Riddle else if (failed(convertExpressionTo(initializer, type))) 255711d26bd1SRiver Riddle return failure(); 255811d26bd1SRiver Riddle 255911d26bd1SRiver Riddle // Otherwise, if there is no initializer check that the type has already 256011d26bd1SRiver Riddle // been resolved from the constraint list. 256111d26bd1SRiver Riddle } else if (!type) { 256211d26bd1SRiver Riddle return emitErrorAndNote( 256311d26bd1SRiver Riddle loc, "unable to infer type for variable `" + name + "`", loc, 256411d26bd1SRiver Riddle "the type of a variable must be inferable from the constraint " 256511d26bd1SRiver Riddle "list or the initializer"); 256611d26bd1SRiver Riddle } 256711d26bd1SRiver Riddle 2568faf42264SRiver Riddle // Constraint types cannot be used when defining variables. 2569d2353695SPeiming Liu if (isa<ast::ConstraintType, ast::RewriteType>(type)) { 2570faf42264SRiver Riddle return emitError( 2571faf42264SRiver Riddle loc, llvm::formatv("unable to define variable of `{0}` type", type)); 2572faf42264SRiver Riddle } 2573faf42264SRiver Riddle 257411d26bd1SRiver Riddle // Try to define a variable with the given name. 257511d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> varDecl = 257611d26bd1SRiver Riddle defineVariableDecl(name, loc, type, initializer, constraints); 257711d26bd1SRiver Riddle if (failed(varDecl)) 257811d26bd1SRiver Riddle return failure(); 257911d26bd1SRiver Riddle 258011d26bd1SRiver Riddle return *varDecl; 258111d26bd1SRiver Riddle } 258211d26bd1SRiver Riddle 2583faf42264SRiver Riddle FailureOr<ast::VariableDecl *> 2584faf42264SRiver Riddle Parser::createArgOrResultVariableDecl(StringRef name, SMRange loc, 2585faf42264SRiver Riddle const ast::ConstraintRef &constraint) { 2586faf42264SRiver Riddle ast::Type argType; 2587b6ec1de7SRiver Riddle if (failed(validateVariableConstraint(constraint, argType))) 2588faf42264SRiver Riddle return failure(); 2589faf42264SRiver Riddle return defineVariableDecl(name, loc, argType, constraint); 2590faf42264SRiver Riddle } 2591faf42264SRiver Riddle 259211d26bd1SRiver Riddle LogicalResult 259311d26bd1SRiver Riddle Parser::validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints, 2594b6ec1de7SRiver Riddle ast::Type &inferredType) { 259511d26bd1SRiver Riddle for (const ast::ConstraintRef &ref : constraints) 2596b6ec1de7SRiver Riddle if (failed(validateVariableConstraint(ref, inferredType))) 259711d26bd1SRiver Riddle return failure(); 259811d26bd1SRiver Riddle return success(); 259911d26bd1SRiver Riddle } 260011d26bd1SRiver Riddle 260111d26bd1SRiver Riddle LogicalResult Parser::validateVariableConstraint(const ast::ConstraintRef &ref, 2602b6ec1de7SRiver Riddle ast::Type &inferredType) { 260311d26bd1SRiver Riddle ast::Type constraintType; 260411d26bd1SRiver Riddle if (const auto *cst = dyn_cast<ast::AttrConstraintDecl>(ref.constraint)) { 260511d26bd1SRiver Riddle if (const ast::Expr *typeExpr = cst->getTypeExpr()) { 260611d26bd1SRiver Riddle if (failed(validateTypeConstraintExpr(typeExpr))) 260711d26bd1SRiver Riddle return failure(); 260811d26bd1SRiver Riddle } 260911d26bd1SRiver Riddle constraintType = ast::AttributeType::get(ctx); 261011d26bd1SRiver Riddle } else if (const auto *cst = 261111d26bd1SRiver Riddle dyn_cast<ast::OpConstraintDecl>(ref.constraint)) { 26121c2edb02SRiver Riddle constraintType = ast::OperationType::get( 26131c2edb02SRiver Riddle ctx, cst->getName(), lookupODSOperation(cst->getName())); 261411d26bd1SRiver Riddle } else if (isa<ast::TypeConstraintDecl>(ref.constraint)) { 261511d26bd1SRiver Riddle constraintType = typeTy; 261611d26bd1SRiver Riddle } else if (isa<ast::TypeRangeConstraintDecl>(ref.constraint)) { 261711d26bd1SRiver Riddle constraintType = typeRangeTy; 261811d26bd1SRiver Riddle } else if (const auto *cst = 261911d26bd1SRiver Riddle dyn_cast<ast::ValueConstraintDecl>(ref.constraint)) { 262011d26bd1SRiver Riddle if (const ast::Expr *typeExpr = cst->getTypeExpr()) { 262111d26bd1SRiver Riddle if (failed(validateTypeConstraintExpr(typeExpr))) 262211d26bd1SRiver Riddle return failure(); 262311d26bd1SRiver Riddle } 262411d26bd1SRiver Riddle constraintType = valueTy; 262511d26bd1SRiver Riddle } else if (const auto *cst = 262611d26bd1SRiver Riddle dyn_cast<ast::ValueRangeConstraintDecl>(ref.constraint)) { 262711d26bd1SRiver Riddle if (const ast::Expr *typeExpr = cst->getTypeExpr()) { 262811d26bd1SRiver Riddle if (failed(validateTypeRangeConstraintExpr(typeExpr))) 262911d26bd1SRiver Riddle return failure(); 263011d26bd1SRiver Riddle } 263111d26bd1SRiver Riddle constraintType = valueRangeTy; 2632faf42264SRiver Riddle } else if (const auto *cst = 2633faf42264SRiver Riddle dyn_cast<ast::UserConstraintDecl>(ref.constraint)) { 2634faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> inputs = cst->getInputs(); 2635faf42264SRiver Riddle if (inputs.size() != 1) { 2636faf42264SRiver Riddle return emitErrorAndNote(ref.referenceLoc, 2637faf42264SRiver Riddle "`Constraint`s applied via a variable constraint " 2638faf42264SRiver Riddle "list must take a single input, but got " + 2639faf42264SRiver Riddle Twine(inputs.size()), 2640faf42264SRiver Riddle cst->getLoc(), 2641faf42264SRiver Riddle "see definition of constraint here"); 2642faf42264SRiver Riddle } 2643faf42264SRiver Riddle constraintType = inputs.front()->getType(); 264411d26bd1SRiver Riddle } else { 264511d26bd1SRiver Riddle llvm_unreachable("unknown constraint type"); 264611d26bd1SRiver Riddle } 264711d26bd1SRiver Riddle 264811d26bd1SRiver Riddle // Check that the constraint type is compatible with the current inferred 264911d26bd1SRiver Riddle // type. 265011d26bd1SRiver Riddle if (!inferredType) { 265111d26bd1SRiver Riddle inferredType = constraintType; 265211d26bd1SRiver Riddle } else if (ast::Type mergedTy = inferredType.refineWith(constraintType)) { 265311d26bd1SRiver Riddle inferredType = mergedTy; 265411d26bd1SRiver Riddle } else { 265511d26bd1SRiver Riddle return emitError(ref.referenceLoc, 265611d26bd1SRiver Riddle llvm::formatv("constraint type `{0}` is incompatible " 265711d26bd1SRiver Riddle "with the previously inferred type `{1}`", 265811d26bd1SRiver Riddle constraintType, inferredType)); 265911d26bd1SRiver Riddle } 266011d26bd1SRiver Riddle return success(); 266111d26bd1SRiver Riddle } 266211d26bd1SRiver Riddle 266311d26bd1SRiver Riddle LogicalResult Parser::validateTypeConstraintExpr(const ast::Expr *typeExpr) { 266411d26bd1SRiver Riddle ast::Type typeExprType = typeExpr->getType(); 266511d26bd1SRiver Riddle if (typeExprType != typeTy) { 266611d26bd1SRiver Riddle return emitError(typeExpr->getLoc(), 266711d26bd1SRiver Riddle "expected expression of `Type` in type constraint"); 266811d26bd1SRiver Riddle } 266911d26bd1SRiver Riddle return success(); 267011d26bd1SRiver Riddle } 267111d26bd1SRiver Riddle 267211d26bd1SRiver Riddle LogicalResult 267311d26bd1SRiver Riddle Parser::validateTypeRangeConstraintExpr(const ast::Expr *typeExpr) { 267411d26bd1SRiver Riddle ast::Type typeExprType = typeExpr->getType(); 267511d26bd1SRiver Riddle if (typeExprType != typeRangeTy) { 267611d26bd1SRiver Riddle return emitError(typeExpr->getLoc(), 267711d26bd1SRiver Riddle "expected expression of `TypeRange` in type constraint"); 267811d26bd1SRiver Riddle } 267911d26bd1SRiver Riddle return success(); 268011d26bd1SRiver Riddle } 268111d26bd1SRiver Riddle 268211d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 268311d26bd1SRiver Riddle // Exprs 268411d26bd1SRiver Riddle 2685faf42264SRiver Riddle FailureOr<ast::CallExpr *> 2686faf42264SRiver Riddle Parser::createCallExpr(SMRange loc, ast::Expr *parentExpr, 2687930916c7SMogball MutableArrayRef<ast::Expr *> arguments, bool isNegated) { 2688faf42264SRiver Riddle ast::Type parentType = parentExpr->getType(); 2689faf42264SRiver Riddle 2690faf42264SRiver Riddle ast::CallableDecl *callableDecl = tryExtractCallableDecl(parentExpr); 2691faf42264SRiver Riddle if (!callableDecl) { 2692faf42264SRiver Riddle return emitError(loc, 2693faf42264SRiver Riddle llvm::formatv("expected a reference to a callable " 2694faf42264SRiver Riddle "`Constraint` or `Rewrite`, but got: `{0}`", 2695faf42264SRiver Riddle parentType)); 2696faf42264SRiver Riddle } 2697faf42264SRiver Riddle if (parserContext == ParserContext::Rewrite) { 2698faf42264SRiver Riddle if (isa<ast::UserConstraintDecl>(callableDecl)) 2699faf42264SRiver Riddle return emitError( 2700faf42264SRiver Riddle loc, "unable to invoke `Constraint` within a rewrite section"); 2701930916c7SMogball if (isNegated) 2702930916c7SMogball return emitError(loc, "unable to negate a Rewrite"); 2703930916c7SMogball } else { 2704930916c7SMogball if (isa<ast::UserRewriteDecl>(callableDecl)) 2705930916c7SMogball return emitError(loc, 2706930916c7SMogball "unable to invoke `Rewrite` within a match section"); 2707930916c7SMogball if (isNegated && cast<ast::UserConstraintDecl>(callableDecl)->getBody()) 2708930916c7SMogball return emitError(loc, "unable to negate non native constraints"); 2709faf42264SRiver Riddle } 2710faf42264SRiver Riddle 2711faf42264SRiver Riddle // Verify the arguments of the call. 2712faf42264SRiver Riddle /// Handle size mismatch. 2713faf42264SRiver Riddle ArrayRef<ast::VariableDecl *> callArgs = callableDecl->getInputs(); 2714faf42264SRiver Riddle if (callArgs.size() != arguments.size()) { 2715faf42264SRiver Riddle return emitErrorAndNote( 2716faf42264SRiver Riddle loc, 2717faf42264SRiver Riddle llvm::formatv("invalid number of arguments for {0} call; expected " 2718faf42264SRiver Riddle "{1}, but got {2}", 2719faf42264SRiver Riddle callableDecl->getCallableType(), callArgs.size(), 2720faf42264SRiver Riddle arguments.size()), 2721faf42264SRiver Riddle callableDecl->getLoc(), 2722faf42264SRiver Riddle llvm::formatv("see the definition of {0} here", 2723faf42264SRiver Riddle callableDecl->getName()->getName())); 2724faf42264SRiver Riddle } 2725faf42264SRiver Riddle 2726faf42264SRiver Riddle /// Handle argument type mismatch. 2727faf42264SRiver Riddle auto attachDiagFn = [&](ast::Diagnostic &diag) { 2728faf42264SRiver Riddle diag.attachNote(llvm::formatv("see the definition of `{0}` here", 2729faf42264SRiver Riddle callableDecl->getName()->getName()), 2730faf42264SRiver Riddle callableDecl->getLoc()); 2731faf42264SRiver Riddle }; 2732faf42264SRiver Riddle for (auto it : llvm::zip(callArgs, arguments)) { 2733faf42264SRiver Riddle if (failed(convertExpressionTo(std::get<1>(it), std::get<0>(it)->getType(), 2734faf42264SRiver Riddle attachDiagFn))) 2735faf42264SRiver Riddle return failure(); 2736faf42264SRiver Riddle } 2737faf42264SRiver Riddle 2738faf42264SRiver Riddle return ast::CallExpr::create(ctx, loc, parentExpr, arguments, 2739930916c7SMogball callableDecl->getResultType(), isNegated); 2740faf42264SRiver Riddle } 2741faf42264SRiver Riddle 27426842ec42SRiver Riddle FailureOr<ast::DeclRefExpr *> Parser::createDeclRefExpr(SMRange loc, 274311d26bd1SRiver Riddle ast::Decl *decl) { 274411d26bd1SRiver Riddle // Check the type of decl being referenced. 274511d26bd1SRiver Riddle ast::Type declType; 2746faf42264SRiver Riddle if (isa<ast::ConstraintDecl>(decl)) 2747faf42264SRiver Riddle declType = ast::ConstraintType::get(ctx); 2748faf42264SRiver Riddle else if (isa<ast::UserRewriteDecl>(decl)) 2749faf42264SRiver Riddle declType = ast::RewriteType::get(ctx); 2750faf42264SRiver Riddle else if (auto *varDecl = dyn_cast<ast::VariableDecl>(decl)) 275111d26bd1SRiver Riddle declType = varDecl->getType(); 275211d26bd1SRiver Riddle else 275311d26bd1SRiver Riddle return emitError(loc, "invalid reference to `" + 275411d26bd1SRiver Riddle decl->getName()->getName() + "`"); 275511d26bd1SRiver Riddle 275611d26bd1SRiver Riddle return ast::DeclRefExpr::create(ctx, loc, decl, declType); 275711d26bd1SRiver Riddle } 275811d26bd1SRiver Riddle 275911d26bd1SRiver Riddle FailureOr<ast::DeclRefExpr *> 2760faf42264SRiver Riddle Parser::createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc, 276111d26bd1SRiver Riddle ArrayRef<ast::ConstraintRef> constraints) { 276211d26bd1SRiver Riddle FailureOr<ast::VariableDecl *> decl = 276311d26bd1SRiver Riddle defineVariableDecl(name, loc, type, constraints); 276411d26bd1SRiver Riddle if (failed(decl)) 276511d26bd1SRiver Riddle return failure(); 276611d26bd1SRiver Riddle return ast::DeclRefExpr::create(ctx, loc, *decl, type); 276711d26bd1SRiver Riddle } 276811d26bd1SRiver Riddle 276911d26bd1SRiver Riddle FailureOr<ast::MemberAccessExpr *> 277011d26bd1SRiver Riddle Parser::createMemberAccessExpr(ast::Expr *parentExpr, StringRef name, 27716842ec42SRiver Riddle SMRange loc) { 277211d26bd1SRiver Riddle // Validate the member name for the given parent expression. 277311d26bd1SRiver Riddle FailureOr<ast::Type> memberType = validateMemberAccess(parentExpr, name, loc); 277411d26bd1SRiver Riddle if (failed(memberType)) 277511d26bd1SRiver Riddle return failure(); 277611d26bd1SRiver Riddle 277711d26bd1SRiver Riddle return ast::MemberAccessExpr::create(ctx, loc, parentExpr, name, *memberType); 277811d26bd1SRiver Riddle } 277911d26bd1SRiver Riddle 278011d26bd1SRiver Riddle FailureOr<ast::Type> Parser::validateMemberAccess(ast::Expr *parentExpr, 2781faf42264SRiver Riddle StringRef name, SMRange loc) { 278211d26bd1SRiver Riddle ast::Type parentType = parentExpr->getType(); 2783d2353695SPeiming Liu if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType)) { 278402670c3fSRiver Riddle if (name == ast::AllResultsMemberAccessExpr::getMemberName()) 278511d26bd1SRiver Riddle return valueRangeTy; 278681f2f4dfSRiver Riddle 278781f2f4dfSRiver Riddle // Verify member access based on the operation type. 27881c2edb02SRiver Riddle if (const ods::Operation *odsOp = opType.getODSOperation()) { 278981f2f4dfSRiver Riddle auto results = odsOp->getResults(); 279081f2f4dfSRiver Riddle 279181f2f4dfSRiver Riddle // Handle indexed results. 279281f2f4dfSRiver Riddle unsigned index = 0; 279381f2f4dfSRiver Riddle if (llvm::isDigit(name[0]) && !name.getAsInteger(/*Radix=*/10, index) && 279481f2f4dfSRiver Riddle index < results.size()) { 279581f2f4dfSRiver Riddle return results[index].isVariadic() ? valueRangeTy : valueTy; 279681f2f4dfSRiver Riddle } 279781f2f4dfSRiver Riddle 279881f2f4dfSRiver Riddle // Handle named results. 279981f2f4dfSRiver Riddle const auto *it = llvm::find_if(results, [&](const auto &result) { 280081f2f4dfSRiver Riddle return result.getName() == name; 280181f2f4dfSRiver Riddle }); 280281f2f4dfSRiver Riddle if (it != results.end()) 280381f2f4dfSRiver Riddle return it->isVariadic() ? valueRangeTy : valueTy; 2804c088fbe7SChia-hung Duan } else if (llvm::isDigit(name[0])) { 2805c088fbe7SChia-hung Duan // Allow unchecked numeric indexing of the results of unregistered 2806c088fbe7SChia-hung Duan // operations. It returns a single value. 2807c088fbe7SChia-hung Duan return valueTy; 280881f2f4dfSRiver Riddle } 2809d2353695SPeiming Liu } else if (auto tupleType = dyn_cast<ast::TupleType>(parentType)) { 2810f62a57a3SRiver Riddle // Handle indexed results. 2811f62a57a3SRiver Riddle unsigned index = 0; 2812f62a57a3SRiver Riddle if (llvm::isDigit(name[0]) && !name.getAsInteger(/*Radix=*/10, index) && 2813f62a57a3SRiver Riddle index < tupleType.size()) { 2814f62a57a3SRiver Riddle return tupleType.getElementTypes()[index]; 2815f62a57a3SRiver Riddle } 2816f62a57a3SRiver Riddle 2817f62a57a3SRiver Riddle // Handle named results. 2818f62a57a3SRiver Riddle auto elementNames = tupleType.getElementNames(); 281902b6fb21SMehdi Amini const auto *it = llvm::find(elementNames, name); 2820f62a57a3SRiver Riddle if (it != elementNames.end()) 2821f62a57a3SRiver Riddle return tupleType.getElementTypes()[it - elementNames.begin()]; 282211d26bd1SRiver Riddle } 282311d26bd1SRiver Riddle return emitError( 282411d26bd1SRiver Riddle loc, 282511d26bd1SRiver Riddle llvm::formatv("invalid member access `{0}` on expression of type `{1}`", 282611d26bd1SRiver Riddle name, parentType)); 282711d26bd1SRiver Riddle } 282811d26bd1SRiver Riddle 282902670c3fSRiver Riddle FailureOr<ast::OperationExpr *> Parser::createOperationExpr( 28306842ec42SRiver Riddle SMRange loc, const ast::OpNameDecl *name, 283191b8d96fSRiver Riddle OpResultTypeContext resultTypeContext, 2832ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &operands, 283302670c3fSRiver Riddle MutableArrayRef<ast::NamedAttributeDecl *> attributes, 2834ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &results) { 28350a81ace0SKazu Hirata std::optional<StringRef> opNameRef = name->getName(); 283681f2f4dfSRiver Riddle const ods::Operation *odsOp = lookupODSOperation(opNameRef); 283702670c3fSRiver Riddle 283802670c3fSRiver Riddle // Verify the inputs operands. 283981f2f4dfSRiver Riddle if (failed(validateOperationOperands(loc, opNameRef, odsOp, operands))) 284002670c3fSRiver Riddle return failure(); 284102670c3fSRiver Riddle 284202670c3fSRiver Riddle // Verify the attribute list. 284302670c3fSRiver Riddle for (ast::NamedAttributeDecl *attr : attributes) { 284402670c3fSRiver Riddle // Check for an attribute type, or a type awaiting resolution. 284502670c3fSRiver Riddle ast::Type attrType = attr->getValue()->getType(); 2846d2353695SPeiming Liu if (!isa<ast::AttributeType>(attrType)) { 284702670c3fSRiver Riddle return emitError( 284802670c3fSRiver Riddle attr->getValue()->getLoc(), 284902670c3fSRiver Riddle llvm::formatv("expected `Attr` expression, but got `{0}`", attrType)); 285002670c3fSRiver Riddle } 285102670c3fSRiver Riddle } 285202670c3fSRiver Riddle 285391b8d96fSRiver Riddle assert( 285491b8d96fSRiver Riddle (resultTypeContext == OpResultTypeContext::Explicit || results.empty()) && 285591b8d96fSRiver Riddle "unexpected inferrence when results were explicitly specified"); 285691b8d96fSRiver Riddle 285791b8d96fSRiver Riddle // If we aren't relying on type inferrence, or explicit results were provided, 285891b8d96fSRiver Riddle // validate them. 285991b8d96fSRiver Riddle if (resultTypeContext == OpResultTypeContext::Explicit) { 286081f2f4dfSRiver Riddle if (failed(validateOperationResults(loc, opNameRef, odsOp, results))) 286102670c3fSRiver Riddle return failure(); 286202670c3fSRiver Riddle 286391b8d96fSRiver Riddle // Validate the use of interface based type inferrence for this operation. 286491b8d96fSRiver Riddle } else if (resultTypeContext == OpResultTypeContext::Interface) { 286591b8d96fSRiver Riddle assert(opNameRef && 286691b8d96fSRiver Riddle "expected valid operation name when inferring operation results"); 286791b8d96fSRiver Riddle checkOperationResultTypeInferrence(loc, *opNameRef, odsOp); 286891b8d96fSRiver Riddle } 286991b8d96fSRiver Riddle 28701c2edb02SRiver Riddle return ast::OperationExpr::create(ctx, loc, odsOp, name, operands, results, 287102670c3fSRiver Riddle attributes); 287202670c3fSRiver Riddle } 287302670c3fSRiver Riddle 287402670c3fSRiver Riddle LogicalResult 28750a81ace0SKazu Hirata Parser::validateOperationOperands(SMRange loc, std::optional<StringRef> name, 287681f2f4dfSRiver Riddle const ods::Operation *odsOp, 2877ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &operands) { 287881f2f4dfSRiver Riddle return validateOperationOperandsOrResults( 28790a81ace0SKazu Hirata "operand", loc, odsOp ? odsOp->getLoc() : std::optional<SMRange>(), name, 28801a36588eSKazu Hirata operands, odsOp ? odsOp->getOperands() : std::nullopt, valueTy, 288102670c3fSRiver Riddle valueRangeTy); 288202670c3fSRiver Riddle } 288302670c3fSRiver Riddle 288402670c3fSRiver Riddle LogicalResult 28850a81ace0SKazu Hirata Parser::validateOperationResults(SMRange loc, std::optional<StringRef> name, 288681f2f4dfSRiver Riddle const ods::Operation *odsOp, 2887ec92a125SRiver Riddle SmallVectorImpl<ast::Expr *> &results) { 288881f2f4dfSRiver Riddle return validateOperationOperandsOrResults( 28890a81ace0SKazu Hirata "result", loc, odsOp ? odsOp->getLoc() : std::optional<SMRange>(), name, 28901a36588eSKazu Hirata results, odsOp ? odsOp->getResults() : std::nullopt, typeTy, typeRangeTy); 289102670c3fSRiver Riddle } 289202670c3fSRiver Riddle 289391b8d96fSRiver Riddle void Parser::checkOperationResultTypeInferrence(SMRange loc, StringRef opName, 289491b8d96fSRiver Riddle const ods::Operation *odsOp) { 289591b8d96fSRiver Riddle // If the operation might not have inferrence support, emit a warning to the 289691b8d96fSRiver Riddle // user. We don't emit an error because the interface might be added to the 289791b8d96fSRiver Riddle // operation at runtime. It's rare, but it could still happen. We emit a 289891b8d96fSRiver Riddle // warning here instead. 289991b8d96fSRiver Riddle 290091b8d96fSRiver Riddle // Handle inferrence warnings for unknown operations. 290191b8d96fSRiver Riddle if (!odsOp) { 290291b8d96fSRiver Riddle ctx.getDiagEngine().emitWarning( 290391b8d96fSRiver Riddle loc, llvm::formatv( 290491b8d96fSRiver Riddle "operation result types are marked to be inferred, but " 290591b8d96fSRiver Riddle "`{0}` is unknown. Ensure that `{0}` supports zero " 290691b8d96fSRiver Riddle "results or implements `InferTypeOpInterface`. Include " 290791b8d96fSRiver Riddle "the ODS definition of this operation to remove this warning.", 290891b8d96fSRiver Riddle opName)); 290991b8d96fSRiver Riddle return; 291091b8d96fSRiver Riddle } 291191b8d96fSRiver Riddle 291291b8d96fSRiver Riddle // Handle inferrence warnings for known operations that expected at least one 291391b8d96fSRiver Riddle // result, but don't have inference support. An elided results list can mean 291491b8d96fSRiver Riddle // "zero-results", and we don't want to warn when that is the expected 291591b8d96fSRiver Riddle // behavior. 291691b8d96fSRiver Riddle bool requiresInferrence = 291791b8d96fSRiver Riddle llvm::any_of(odsOp->getResults(), [](const ods::OperandOrResult &result) { 291891b8d96fSRiver Riddle return !result.isVariableLength(); 291991b8d96fSRiver Riddle }); 292091b8d96fSRiver Riddle if (requiresInferrence && !odsOp->hasResultTypeInferrence()) { 292191b8d96fSRiver Riddle ast::InFlightDiagnostic diag = ctx.getDiagEngine().emitWarning( 292291b8d96fSRiver Riddle loc, 292391b8d96fSRiver Riddle llvm::formatv("operation result types are marked to be inferred, but " 292491b8d96fSRiver Riddle "`{0}` does not provide an implementation of " 292591b8d96fSRiver Riddle "`InferTypeOpInterface`. Ensure that `{0}` attaches " 292691b8d96fSRiver Riddle "`InferTypeOpInterface` at runtime, or add support to " 292791b8d96fSRiver Riddle "the ODS definition to remove this warning.", 292891b8d96fSRiver Riddle opName)); 292991b8d96fSRiver Riddle diag->attachNote(llvm::formatv("see the definition of `{0}` here", opName), 293091b8d96fSRiver Riddle odsOp->getLoc()); 293191b8d96fSRiver Riddle return; 293291b8d96fSRiver Riddle } 293391b8d96fSRiver Riddle } 293491b8d96fSRiver Riddle 293502670c3fSRiver Riddle LogicalResult Parser::validateOperationOperandsOrResults( 29360a81ace0SKazu Hirata StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc, 29370a81ace0SKazu Hirata std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values, 293881f2f4dfSRiver Riddle ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy, 2939ec92a125SRiver Riddle ast::RangeType rangeTy) { 294002670c3fSRiver Riddle // All operation types accept a single range parameter. 294102670c3fSRiver Riddle if (values.size() == 1) { 294202670c3fSRiver Riddle if (failed(convertExpressionTo(values[0], rangeTy))) 294302670c3fSRiver Riddle return failure(); 294402670c3fSRiver Riddle return success(); 294502670c3fSRiver Riddle } 294602670c3fSRiver Riddle 294781f2f4dfSRiver Riddle /// If the operation has ODS information, we can more accurately verify the 294881f2f4dfSRiver Riddle /// values. 294981f2f4dfSRiver Riddle if (odsOpLoc) { 2950ec92a125SRiver Riddle auto emitSizeMismatchError = [&] { 295181f2f4dfSRiver Riddle return emitErrorAndNote( 295281f2f4dfSRiver Riddle loc, 295381f2f4dfSRiver Riddle llvm::formatv("invalid number of {0} groups for `{1}`; expected " 295481f2f4dfSRiver Riddle "{2}, but got {3}", 295581f2f4dfSRiver Riddle groupName, *name, odsValues.size(), values.size()), 295681f2f4dfSRiver Riddle *odsOpLoc, llvm::formatv("see the definition of `{0}` here", *name)); 2957ec92a125SRiver Riddle }; 2958ec92a125SRiver Riddle 2959ec92a125SRiver Riddle // Handle the case where no values were provided. 2960ec92a125SRiver Riddle if (values.empty()) { 2961ec92a125SRiver Riddle // If we don't expect any on the ODS side, we are done. 2962ec92a125SRiver Riddle if (odsValues.empty()) 2963ec92a125SRiver Riddle return success(); 2964ec92a125SRiver Riddle 2965ec92a125SRiver Riddle // If we do, check if we actually need to provide values (i.e. if any of 2966ec92a125SRiver Riddle // the values are actually required). 2967ec92a125SRiver Riddle unsigned numVariadic = 0; 2968ec92a125SRiver Riddle for (const auto &odsValue : odsValues) { 2969ec92a125SRiver Riddle if (!odsValue.isVariableLength()) 2970ec92a125SRiver Riddle return emitSizeMismatchError(); 2971ec92a125SRiver Riddle ++numVariadic; 297281f2f4dfSRiver Riddle } 2973ec92a125SRiver Riddle 2974ec92a125SRiver Riddle // If we are in a non-rewrite context, we don't need to do anything more. 2975ec92a125SRiver Riddle // Zero-values is a valid constraint on the operation. 2976ec92a125SRiver Riddle if (parserContext != ParserContext::Rewrite) 2977ec92a125SRiver Riddle return success(); 2978ec92a125SRiver Riddle 2979ec92a125SRiver Riddle // Otherwise, when in a rewrite we may need to provide values to match the 2980ec92a125SRiver Riddle // ODS signature of the operation to create. 2981ec92a125SRiver Riddle 2982ec92a125SRiver Riddle // If we only have one variadic value, just use an empty list. 2983ec92a125SRiver Riddle if (numVariadic == 1) 2984ec92a125SRiver Riddle return success(); 2985ec92a125SRiver Riddle 2986ec92a125SRiver Riddle // Otherwise, create dummy values for each of the entries so that we 2987ec92a125SRiver Riddle // adhere to the ODS signature. 2988ec92a125SRiver Riddle for (unsigned i = 0, e = odsValues.size(); i < e; ++i) { 29891a36588eSKazu Hirata values.push_back(ast::RangeExpr::create( 29901a36588eSKazu Hirata ctx, loc, /*elements=*/std::nullopt, rangeTy)); 2991ec92a125SRiver Riddle } 2992ec92a125SRiver Riddle return success(); 2993ec92a125SRiver Riddle } 2994ec92a125SRiver Riddle 2995ec92a125SRiver Riddle // Verify that the number of values provided matches the number of value 2996ec92a125SRiver Riddle // groups ODS expects. 2997ec92a125SRiver Riddle if (odsValues.size() != values.size()) 2998ec92a125SRiver Riddle return emitSizeMismatchError(); 2999ec92a125SRiver Riddle 300081f2f4dfSRiver Riddle auto diagFn = [&](ast::Diagnostic &diag) { 300181f2f4dfSRiver Riddle diag.attachNote(llvm::formatv("see the definition of `{0}` here", *name), 300281f2f4dfSRiver Riddle *odsOpLoc); 300381f2f4dfSRiver Riddle }; 300481f2f4dfSRiver Riddle for (unsigned i = 0, e = values.size(); i < e; ++i) { 300581f2f4dfSRiver Riddle ast::Type expectedType = odsValues[i].isVariadic() ? rangeTy : singleTy; 300681f2f4dfSRiver Riddle if (failed(convertExpressionTo(values[i], expectedType, diagFn))) 300781f2f4dfSRiver Riddle return failure(); 300881f2f4dfSRiver Riddle } 300981f2f4dfSRiver Riddle return success(); 301081f2f4dfSRiver Riddle } 301181f2f4dfSRiver Riddle 301202670c3fSRiver Riddle // Otherwise, accept the value groups as they have been defined and just 301302670c3fSRiver Riddle // ensure they are one of the expected types. 301402670c3fSRiver Riddle for (ast::Expr *&valueExpr : values) { 301502670c3fSRiver Riddle ast::Type valueExprType = valueExpr->getType(); 301602670c3fSRiver Riddle 301702670c3fSRiver Riddle // Check if this is one of the expected types. 301802670c3fSRiver Riddle if (valueExprType == rangeTy || valueExprType == singleTy) 301902670c3fSRiver Riddle continue; 302002670c3fSRiver Riddle 302102670c3fSRiver Riddle // If the operand is an Operation, allow converting to a Value or 302202670c3fSRiver Riddle // ValueRange. This situations arises quite often with nested operation 302302670c3fSRiver Riddle // expressions: `op<my_dialect.foo>(op<my_dialect.bar>)` 302402670c3fSRiver Riddle if (singleTy == valueTy) { 3025d2353695SPeiming Liu if (isa<ast::OperationType>(valueExprType)) { 302602670c3fSRiver Riddle valueExpr = convertOpToValue(valueExpr); 302702670c3fSRiver Riddle continue; 302802670c3fSRiver Riddle } 302902670c3fSRiver Riddle } 303002670c3fSRiver Riddle 30319e57210aSRiver Riddle // Otherwise, try to convert the expression to a range. 30329e57210aSRiver Riddle if (succeeded(convertExpressionTo(valueExpr, rangeTy))) 30339e57210aSRiver Riddle continue; 30349e57210aSRiver Riddle 303502670c3fSRiver Riddle return emitError( 303602670c3fSRiver Riddle valueExpr->getLoc(), 303702670c3fSRiver Riddle llvm::formatv( 303802670c3fSRiver Riddle "expected `{0}` or `{1}` convertible expression, but got `{2}`", 303902670c3fSRiver Riddle singleTy, rangeTy, valueExprType)); 304002670c3fSRiver Riddle } 304102670c3fSRiver Riddle return success(); 304202670c3fSRiver Riddle } 304302670c3fSRiver Riddle 3044f62a57a3SRiver Riddle FailureOr<ast::TupleExpr *> 30456842ec42SRiver Riddle Parser::createTupleExpr(SMRange loc, ArrayRef<ast::Expr *> elements, 3046f62a57a3SRiver Riddle ArrayRef<StringRef> elementNames) { 3047f62a57a3SRiver Riddle for (const ast::Expr *element : elements) { 3048f62a57a3SRiver Riddle ast::Type eleTy = element->getType(); 3049d2353695SPeiming Liu if (isa<ast::ConstraintType, ast::RewriteType, ast::TupleType>(eleTy)) { 3050f62a57a3SRiver Riddle return emitError( 3051f62a57a3SRiver Riddle element->getLoc(), 3052f62a57a3SRiver Riddle llvm::formatv("unable to build a tuple with `{0}` element", eleTy)); 3053f62a57a3SRiver Riddle } 3054f62a57a3SRiver Riddle } 3055f62a57a3SRiver Riddle return ast::TupleExpr::create(ctx, loc, elements, elementNames); 3056f62a57a3SRiver Riddle } 3057f62a57a3SRiver Riddle 305811d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 305911d26bd1SRiver Riddle // Stmts 306011d26bd1SRiver Riddle 30616842ec42SRiver Riddle FailureOr<ast::EraseStmt *> Parser::createEraseStmt(SMRange loc, 306211d26bd1SRiver Riddle ast::Expr *rootOp) { 306311d26bd1SRiver Riddle // Check that root is an Operation. 306411d26bd1SRiver Riddle ast::Type rootType = rootOp->getType(); 3065d2353695SPeiming Liu if (!isa<ast::OperationType>(rootType)) 306611d26bd1SRiver Riddle return emitError(rootOp->getLoc(), "expected `Op` expression"); 306711d26bd1SRiver Riddle 306811d26bd1SRiver Riddle return ast::EraseStmt::create(ctx, loc, rootOp); 306911d26bd1SRiver Riddle } 307011d26bd1SRiver Riddle 307112eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *> 30726842ec42SRiver Riddle Parser::createReplaceStmt(SMRange loc, ast::Expr *rootOp, 307312eebb8eSRiver Riddle MutableArrayRef<ast::Expr *> replValues) { 307412eebb8eSRiver Riddle // Check that root is an Operation. 307512eebb8eSRiver Riddle ast::Type rootType = rootOp->getType(); 3076d2353695SPeiming Liu if (!isa<ast::OperationType>(rootType)) { 307712eebb8eSRiver Riddle return emitError( 307812eebb8eSRiver Riddle rootOp->getLoc(), 307912eebb8eSRiver Riddle llvm::formatv("expected `Op` expression, but got `{0}`", rootType)); 308012eebb8eSRiver Riddle } 308112eebb8eSRiver Riddle 308212eebb8eSRiver Riddle // If there are multiple replacement values, we implicitly convert any Op 308312eebb8eSRiver Riddle // expressions to the value form. 308412eebb8eSRiver Riddle bool shouldConvertOpToValues = replValues.size() > 1; 308512eebb8eSRiver Riddle for (ast::Expr *&replExpr : replValues) { 308612eebb8eSRiver Riddle ast::Type replType = replExpr->getType(); 308712eebb8eSRiver Riddle 308812eebb8eSRiver Riddle // Check that replExpr is an Operation, Value, or ValueRange. 3089d2353695SPeiming Liu if (isa<ast::OperationType>(replType)) { 309012eebb8eSRiver Riddle if (shouldConvertOpToValues) 309112eebb8eSRiver Riddle replExpr = convertOpToValue(replExpr); 309212eebb8eSRiver Riddle continue; 309312eebb8eSRiver Riddle } 309412eebb8eSRiver Riddle 309512eebb8eSRiver Riddle if (replType != valueTy && replType != valueRangeTy) { 309612eebb8eSRiver Riddle return emitError(replExpr->getLoc(), 309712eebb8eSRiver Riddle llvm::formatv("expected `Op`, `Value` or `ValueRange` " 309812eebb8eSRiver Riddle "expression, but got `{0}`", 309912eebb8eSRiver Riddle replType)); 310012eebb8eSRiver Riddle } 310112eebb8eSRiver Riddle } 310212eebb8eSRiver Riddle 310312eebb8eSRiver Riddle return ast::ReplaceStmt::create(ctx, loc, rootOp, replValues); 310412eebb8eSRiver Riddle } 310512eebb8eSRiver Riddle 31063ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *> 31076842ec42SRiver Riddle Parser::createRewriteStmt(SMRange loc, ast::Expr *rootOp, 31083ee44cb7SRiver Riddle ast::CompoundStmt *rewriteBody) { 31093ee44cb7SRiver Riddle // Check that root is an Operation. 31103ee44cb7SRiver Riddle ast::Type rootType = rootOp->getType(); 3111d2353695SPeiming Liu if (!isa<ast::OperationType>(rootType)) { 31123ee44cb7SRiver Riddle return emitError( 31133ee44cb7SRiver Riddle rootOp->getLoc(), 31143ee44cb7SRiver Riddle llvm::formatv("expected `Op` expression, but got `{0}`", rootType)); 31153ee44cb7SRiver Riddle } 31163ee44cb7SRiver Riddle 31173ee44cb7SRiver Riddle return ast::RewriteStmt::create(ctx, loc, rootOp, rewriteBody); 31183ee44cb7SRiver Riddle } 31193ee44cb7SRiver Riddle 312011d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 3121008de486SRiver Riddle // Code Completion 3122008de486SRiver Riddle //===----------------------------------------------------------------------===// 3123008de486SRiver Riddle 3124008de486SRiver Riddle LogicalResult Parser::codeCompleteMemberAccess(ast::Expr *parentExpr) { 3125008de486SRiver Riddle ast::Type parentType = parentExpr->getType(); 3126d2353695SPeiming Liu if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType)) 3127008de486SRiver Riddle codeCompleteContext->codeCompleteOperationMemberAccess(opType); 3128d2353695SPeiming Liu else if (ast::TupleType tupleType = dyn_cast<ast::TupleType>(parentType)) 3129008de486SRiver Riddle codeCompleteContext->codeCompleteTupleMemberAccess(tupleType); 3130008de486SRiver Riddle return failure(); 3131008de486SRiver Riddle } 3132008de486SRiver Riddle 31330a81ace0SKazu Hirata LogicalResult 31340a81ace0SKazu Hirata Parser::codeCompleteAttributeName(std::optional<StringRef> opName) { 3135008de486SRiver Riddle if (opName) 3136008de486SRiver Riddle codeCompleteContext->codeCompleteOperationAttributeName(*opName); 3137008de486SRiver Riddle return failure(); 3138008de486SRiver Riddle } 3139008de486SRiver Riddle 3140008de486SRiver Riddle LogicalResult 3141008de486SRiver Riddle Parser::codeCompleteConstraintName(ast::Type inferredType, 3142008de486SRiver Riddle bool allowInlineTypeConstraints) { 3143008de486SRiver Riddle codeCompleteContext->codeCompleteConstraintName( 3144b6ec1de7SRiver Riddle inferredType, allowInlineTypeConstraints, curDeclScope); 3145008de486SRiver Riddle return failure(); 3146008de486SRiver Riddle } 3147008de486SRiver Riddle 3148008de486SRiver Riddle LogicalResult Parser::codeCompleteDialectName() { 3149008de486SRiver Riddle codeCompleteContext->codeCompleteDialectName(); 3150008de486SRiver Riddle return failure(); 3151008de486SRiver Riddle } 3152008de486SRiver Riddle 3153008de486SRiver Riddle LogicalResult Parser::codeCompleteOperationName(StringRef dialectName) { 3154008de486SRiver Riddle codeCompleteContext->codeCompleteOperationName(dialectName); 3155008de486SRiver Riddle return failure(); 3156008de486SRiver Riddle } 3157008de486SRiver Riddle 3158008de486SRiver Riddle LogicalResult Parser::codeCompletePatternMetadata() { 3159008de486SRiver Riddle codeCompleteContext->codeCompletePatternMetadata(); 3160008de486SRiver Riddle return failure(); 3161008de486SRiver Riddle } 3162008de486SRiver Riddle 316341d2c6dfSRiver Riddle LogicalResult Parser::codeCompleteIncludeFilename(StringRef curPath) { 316441d2c6dfSRiver Riddle codeCompleteContext->codeCompleteIncludeFilename(curPath); 316541d2c6dfSRiver Riddle return failure(); 316641d2c6dfSRiver Riddle } 316741d2c6dfSRiver Riddle 3168469c5894SRiver Riddle void Parser::codeCompleteCallSignature(ast::Node *parent, 3169469c5894SRiver Riddle unsigned currentNumArgs) { 3170469c5894SRiver Riddle ast::CallableDecl *callableDecl = tryExtractCallableDecl(parent); 3171469c5894SRiver Riddle if (!callableDecl) 3172469c5894SRiver Riddle return; 3173469c5894SRiver Riddle 3174469c5894SRiver Riddle codeCompleteContext->codeCompleteCallSignature(callableDecl, currentNumArgs); 3175469c5894SRiver Riddle } 3176469c5894SRiver Riddle 3177469c5894SRiver Riddle void Parser::codeCompleteOperationOperandsSignature( 31780a81ace0SKazu Hirata std::optional<StringRef> opName, unsigned currentNumOperands) { 3179469c5894SRiver Riddle codeCompleteContext->codeCompleteOperationOperandsSignature( 3180469c5894SRiver Riddle opName, currentNumOperands); 3181469c5894SRiver Riddle } 3182469c5894SRiver Riddle 31830a81ace0SKazu Hirata void Parser::codeCompleteOperationResultsSignature( 31840a81ace0SKazu Hirata std::optional<StringRef> opName, unsigned currentNumResults) { 3185469c5894SRiver Riddle codeCompleteContext->codeCompleteOperationResultsSignature(opName, 3186469c5894SRiver Riddle currentNumResults); 3187469c5894SRiver Riddle } 3188469c5894SRiver Riddle 3189008de486SRiver Riddle //===----------------------------------------------------------------------===// 319011d26bd1SRiver Riddle // Parser 319111d26bd1SRiver Riddle //===----------------------------------------------------------------------===// 319211d26bd1SRiver Riddle 3193008de486SRiver Riddle FailureOr<ast::Module *> 3194bf352e0bSRiver Riddle mlir::pdll::parsePDLLAST(ast::Context &ctx, llvm::SourceMgr &sourceMgr, 3195bf352e0bSRiver Riddle bool enableDocumentation, 3196008de486SRiver Riddle CodeCompleteContext *codeCompleteContext) { 3197bf352e0bSRiver Riddle Parser parser(ctx, sourceMgr, enableDocumentation, codeCompleteContext); 319811d26bd1SRiver Riddle return parser.parseModule(); 319911d26bd1SRiver Riddle } 3200