diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h --- a/mlir/include/mlir/IR/OpImplementation.h +++ b/mlir/include/mlir/IR/OpImplementation.h @@ -593,6 +593,9 @@ /// Parse a `]` token if present. virtual ParseResult parseOptionalRSquare() = 0; + /// Parse a `...` token. + virtual ParseResult parseEllipsis() = 0; + /// Parse a `...` token if present; virtual ParseResult parseOptionalEllipsis() = 0; diff --git a/mlir/lib/AsmParser/AsmParserImpl.h b/mlir/lib/AsmParser/AsmParserImpl.h --- a/mlir/lib/AsmParser/AsmParserImpl.h +++ b/mlir/lib/AsmParser/AsmParserImpl.h @@ -114,6 +114,11 @@ return success(parser.consumeIf(Token::comma)); } + /// Parses a `...`. + ParseResult parseEllipsis() override { + return parser.parseToken(Token::ellipsis, "expected '...'"); + } + /// Parses a `...` if present. ParseResult parseOptionalEllipsis() override { return success(parser.consumeIf(Token::ellipsis)); diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -797,6 +797,13 @@ }]; } +def TestEllipsisOp : TEST_Op<"ellipsis"> { + let arguments = (ins Variadic:$operands, UnitAttr:$variadic); + let assemblyFormat = [{ + `(` $operands (`...` $variadic^)? `)` attr-dict `:` type($operands) `...` + }]; +} + // This is used to test encoding of a string attribute into an SSA name of a // pretty printed value name. def StringAttrPrettyNameOp diff --git a/mlir/test/mlir-tblgen/op-format.mlir b/mlir/test/mlir-tblgen/op-format.mlir --- a/mlir/test/mlir-tblgen/op-format.mlir +++ b/mlir/test/mlir-tblgen/op-format.mlir @@ -392,6 +392,12 @@ // CHECK: test.format_literal_following_optional_group(5 : i32) : i32 {a} test.format_literal_following_optional_group(5 : i32) : i32 {a} +func.func @variadic(%a: i32) { + // CHECK: test.ellipsis(%{{.*}} ...) : i32 ... + test.ellipsis(%a ...) : i32 ... + return +} + //===----------------------------------------------------------------------===// // Format trait type inference //===----------------------------------------------------------------------===// diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp --- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp @@ -395,6 +395,7 @@ .Case("?", "Question") .Case("+", "Plus") .Case("*", "Star") + .Case("...", "Ellipsis") << "()"; } if (isOptional) { diff --git a/mlir/tools/mlir-tblgen/FormatGen.cpp b/mlir/tools/mlir-tblgen/FormatGen.cpp --- a/mlir/tools/mlir-tblgen/FormatGen.cpp +++ b/mlir/tools/mlir-tblgen/FormatGen.cpp @@ -473,6 +473,8 @@ // Check the punctuation that are larger than a single character. if (value == "->") return true; + if (value == "...") + return true; // Otherwise, this must be an identifier. return canFormatStringAsKeyword(value, emitError); diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp --- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp @@ -760,7 +760,8 @@ .Case("]", "RSquare()") .Case("?", "Question()") .Case("+", "Plus()") - .Case("*", "Star()"); + .Case("*", "Star()") + .Case("...", "Ellipsis()"); } /// Generate the storage code required for parsing the given element.