/// existing constraints that have already been parsed for the same entity
/// that will be constrained by this constraint. `allowInlineTypeConstraints`
/// allows the use of inline Type constraints, e.g. `Value<valueType: Type>`.
- /// If `allowNonCoreConstraints` is true, then complex (e.g. user defined
- /// constraints) may be used with the variable.
FailureOr<ast::ConstraintRef>
parseConstraint(Optional<SMRange> &typeConstraint,
ArrayRef<ast::ConstraintRef> existingConstraints,
- bool allowInlineTypeConstraints,
- bool allowNonCoreConstraints);
+ bool allowInlineTypeConstraints);
/// Try to parse the constraint for a UserConstraintDecl/UserRewriteDecl
/// argument or result variable. The constraints for these variables do not
/// `inferredType` is the type of the variable inferred by the constraints
/// within the list, and is updated to the most refined type as determined by
/// the constraints. Returns success if the constraint list is valid, failure
- /// otherwise. If `allowNonCoreConstraints` is true, then complex (e.g. user
- /// defined constraints) may be used with the variable.
+ /// otherwise.
LogicalResult
validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
- ast::Type &inferredType,
- bool allowNonCoreConstraints = true);
+ ast::Type &inferredType);
/// Validate a single reference to a constraint. `inferredType` contains the
/// currently inferred variabled type and is refined within the type defined
/// by the constraint. Returns success if the constraint is valid, failure
- /// otherwise. If `allowNonCoreConstraints` is true, then complex (e.g. user
- /// defined constraints) may be used with the variable.
+ /// otherwise.
LogicalResult validateVariableConstraint(const ast::ConstraintRef &ref,
- ast::Type &inferredType,
- bool allowNonCoreConstraints = true);
+ ast::Type &inferredType);
LogicalResult validateTypeConstraintExpr(const ast::Expr *typeExpr);
LogicalResult validateTypeRangeConstraintExpr(const ast::Expr *typeExpr);
LogicalResult codeCompleteMemberAccess(ast::Expr *parentExpr);
LogicalResult codeCompleteAttributeName(Optional<StringRef> opName);
LogicalResult codeCompleteConstraintName(ast::Type inferredType,
- bool allowNonCoreConstraints,
bool allowInlineTypeConstraints);
LogicalResult codeCompleteDialectName();
LogicalResult codeCompleteOperationName(StringRef dialectName);
// Check to see if this result is named.
if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) {
// Check to see if this name actually refers to a Constraint.
- ast::Decl *existingDecl = curDeclScope->lookup(curToken.getSpelling());
- if (isa_and_nonnull<ast::ConstraintDecl>(existingDecl)) {
- // If yes, and this is a Rewrite, give a nice error message as non-Core
- // constraints are not supported on Rewrite results.
- if (parserContext == ParserContext::Rewrite) {
- return emitError(
- "`Rewrite` results are only permitted to use core constraints, "
- "such as `Attr`, `Op`, `Type`, `TypeRange`, `Value`, `ValueRange`");
- }
-
- // Otherwise, parse this as an unnamed result variable.
- } else {
+ if (!curDeclScope->lookup<ast::ConstraintDecl>(curToken.getSpelling())) {
// If it wasn't a constraint, parse the result similarly to a variable. If
// there is already an existing decl, we will emit an error when defining
// this variable later.
Optional<SMRange> typeConstraint;
auto parseSingleConstraint = [&] {
FailureOr<ast::ConstraintRef> constraint = parseConstraint(
- typeConstraint, constraints, /*allowInlineTypeConstraints=*/true,
- /*allowNonCoreConstraints=*/true);
+ typeConstraint, constraints, /*allowInlineTypeConstraints=*/true);
if (failed(constraint))
return failure();
constraints.push_back(*constraint);
FailureOr<ast::ConstraintRef>
Parser::parseConstraint(Optional<SMRange> &typeConstraint,
ArrayRef<ast::ConstraintRef> existingConstraints,
- bool allowInlineTypeConstraints,
- bool allowNonCoreConstraints) {
+ bool allowInlineTypeConstraints) {
auto parseTypeConstraint = [&](ast::Expr *&typeExpr) -> LogicalResult {
if (!allowInlineTypeConstraints) {
return emitError(
case Token::code_complete: {
// Try to infer the current type for use by code completion.
ast::Type inferredType;
- if (failed(validateVariableConstraints(existingConstraints, inferredType,
- allowNonCoreConstraints)))
+ if (failed(validateVariableConstraints(existingConstraints, inferredType)))
return failure();
- return codeCompleteConstraintName(inferredType, allowNonCoreConstraints,
- allowInlineTypeConstraints);
+ return codeCompleteConstraintName(inferredType, allowInlineTypeConstraints);
}
default:
break;
}
FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() {
- // Constraint arguments may apply more complex constraints via the arguments.
- bool allowNonCoreConstraints = parserContext == ParserContext::Constraint;
-
Optional<SMRange> typeConstraint;
return parseConstraint(typeConstraint, /*existingConstraints=*/llvm::None,
- /*allowInlineTypeConstraints=*/false,
- allowNonCoreConstraints);
+ /*allowInlineTypeConstraints=*/false);
}
//===----------------------------------------------------------------------===//
FailureOr<ast::VariableDecl *>
Parser::createArgOrResultVariableDecl(StringRef name, SMRange loc,
const ast::ConstraintRef &constraint) {
- // Constraint arguments may apply more complex constraints via the arguments.
- bool allowNonCoreConstraints = parserContext == ParserContext::Constraint;
ast::Type argType;
- if (failed(validateVariableConstraint(constraint, argType,
- allowNonCoreConstraints)))
+ if (failed(validateVariableConstraint(constraint, argType)))
return failure();
return defineVariableDecl(name, loc, argType, constraint);
}
LogicalResult
Parser::validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
- ast::Type &inferredType,
- bool allowNonCoreConstraints) {
+ ast::Type &inferredType) {
for (const ast::ConstraintRef &ref : constraints)
- if (failed(validateVariableConstraint(ref, inferredType,
- allowNonCoreConstraints)))
+ if (failed(validateVariableConstraint(ref, inferredType)))
return failure();
return success();
}
LogicalResult Parser::validateVariableConstraint(const ast::ConstraintRef &ref,
- ast::Type &inferredType,
- bool allowNonCoreConstraints) {
+ ast::Type &inferredType) {
ast::Type constraintType;
if (const auto *cst = dyn_cast<ast::AttrConstraintDecl>(ref.constraint)) {
if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
constraintType = valueRangeTy;
} else if (const auto *cst =
dyn_cast<ast::UserConstraintDecl>(ref.constraint)) {
- if (!allowNonCoreConstraints) {
- return emitError(ref.referenceLoc,
- "`Rewrite` arguments and results are only permitted to "
- "use core constraints, such as `Attr`, `Op`, `Type`, "
- "`TypeRange`, `Value`, `ValueRange`");
- }
-
ArrayRef<ast::VariableDecl *> inputs = cst->getInputs();
if (inputs.size() != 1) {
return emitErrorAndNote(ref.referenceLoc,
LogicalResult
Parser::codeCompleteConstraintName(ast::Type inferredType,
- bool allowNonCoreConstraints,
bool allowInlineTypeConstraints) {
codeCompleteContext->codeCompleteConstraintName(
- inferredType, allowNonCoreConstraints, allowInlineTypeConstraints,
- curDeclScope);
+ inferredType, allowInlineTypeConstraints, curDeclScope);
return failure();
}
-// RUN: mlir-pdll %s -I %S -split-input-file -x cpp | FileCheck %s
+// RUN: mlir-pdll %s -I %S -I %S/../../../../include -split-input-file -x cpp | FileCheck %s
// Check that we generate a wrapper pattern for each PDL pattern. Also
// add in a pattern awkwardly named the same as our generated patterns to
// Check the generation of native constraints and rewrites.
+#include "include/ods.td"
+
// CHECK: static ::mlir::LogicalResult TestCstPDLFn(::mlir::PatternRewriter &rewriter,
// CHECK-SAME: ::mlir::Attribute attr, ::mlir::Operation * op, ::mlir::Type type,
// CHECK-SAME: ::mlir::Value value, ::mlir::TypeRange typeRange, ::mlir::ValueRange valueRange) {
// CHECK: foo;
// CHECK: }
+// CHECK: TestAttrInterface TestRewriteODSPDLFn(::mlir::PatternRewriter &rewriter, TestAttrInterface attr) {
// CHECK: static ::mlir::Attribute TestRewriteSinglePDLFn(::mlir::PatternRewriter &rewriter) {
// CHECK: std::tuple<::mlir::Attribute, ::mlir::Type> TestRewriteTuplePDLFn(::mlir::PatternRewriter &rewriter) {
Constraint TestUnusedCst() [{ return success(); }];
Rewrite TestRewrite(attr: Attr, op: Op, type: Type, value: Value, typeRange: TypeRange, valueRange: ValueRange) [{ foo; }];
+Rewrite TestRewriteODS(attr: TestAttrInterface) -> TestAttrInterface [{}];
Rewrite TestRewriteSingle() -> Attr [{}];
Rewrite TestRewriteTuple() -> (Attr, Type) [{}];
Rewrite TestUnusedRewrite(op: Op) [{}];
TestCst(attr<"true">, root, type, operand, types, operands);
rewrite root with {
TestRewrite(attr<"true">, root, type, operand, types, operands);
+ TestRewriteODS(attr<"true">);
TestRewriteSingle();
TestRewriteTuple();
erase root;