101 changes: 0 additions & 101 deletions mlir/lib/Dialect/PDL/IR/PDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,41 +321,6 @@ bool OperationOp::hasTypeInference() {
// pdl::PatternOp
//===----------------------------------------------------------------------===//

static ParseResult parsePatternOp(OpAsmParser &p, OperationState &state) {
StringAttr name;
p.parseOptionalSymbolName(name, SymbolTable::getSymbolAttrName(),
state.attributes);

// Parse the benefit.
IntegerAttr benefitAttr;
if (p.parseColon() || p.parseKeyword("benefit") || p.parseLParen() ||
p.parseAttribute(benefitAttr, p.getBuilder().getIntegerType(16),
"benefit", state.attributes) ||
p.parseRParen())
return failure();

// Parse the pattern body.
if (p.parseOptionalAttrDictWithKeyword(state.attributes) ||
p.parseRegion(*state.addRegion(), None, None))
return failure();
return success();
}

static void print(OpAsmPrinter &p, PatternOp op) {
p << "pdl.pattern";
if (Optional<StringRef> name = op.sym_name()) {
p << ' ';
p.printSymbolName(*name);
}
p << " : benefit(";
p.printAttributeWithoutType(op.benefitAttr());
p << ")";

p.printOptionalAttrDictWithKeyword(
op.getAttrs(), {"benefit", "rootKind", SymbolTable::getSymbolAttrName()});
p.printRegion(op.body());
}

static LogicalResult verify(PatternOp pattern) {
Region &body = pattern.body();
auto *term = body.front().getTerminator();
Expand Down Expand Up @@ -445,72 +410,6 @@ static LogicalResult verify(ReplaceOp op) {
// pdl::RewriteOp
//===----------------------------------------------------------------------===//

static ParseResult parseRewriteOp(OpAsmParser &p, OperationState &state) {
// Parse the root operand.
OpAsmParser::OperandType rootOperand;
if (p.parseOperand(rootOperand) ||
p.resolveOperand(rootOperand, p.getBuilder().getType<OperationType>(),
state.operands))
return failure();

// Parse an external rewrite.
StringAttr nameAttr;
if (succeeded(p.parseOptionalKeyword("with"))) {
if (p.parseAttribute(nameAttr, "name", state.attributes))
return failure();

// Parse the optional set of constant parameters.
ArrayAttr constantParams;
OptionalParseResult constantParamResult = p.parseOptionalAttribute(
constantParams, "externalConstParams", state.attributes);
if (constantParamResult.hasValue() && failed(*constantParamResult))
return failure();

// Parse the optional additional arguments.
if (succeeded(p.parseOptionalLParen())) {
SmallVector<OpAsmParser::OperandType, 4> arguments;
SmallVector<Type, 4> argumentTypes;
llvm::SMLoc argumentLoc = p.getCurrentLocation();
if (p.parseOperandList(arguments) ||
p.parseColonTypeList(argumentTypes) || p.parseRParen() ||
p.resolveOperands(arguments, argumentTypes, argumentLoc,
state.operands))
return failure();
}
}

// If this isn't an external rewrite, parse the region body.
Region &rewriteRegion = *state.addRegion();
if (!nameAttr) {
if (p.parseRegion(rewriteRegion, /*arguments=*/llvm::None,
/*argTypes=*/llvm::None))
return failure();
RewriteOp::ensureTerminator(rewriteRegion, p.getBuilder(), state.location);
}

return p.parseOptionalAttrDictWithKeyword(state.attributes);
}

static void print(OpAsmPrinter &p, RewriteOp op) {
p << "pdl.rewrite " << op.root();
if (Optional<StringRef> name = op.name()) {
p << " with \"" << *name << "\"";

if (ArrayAttr constantParams = op.externalConstParamsAttr())
p << constantParams;

OperandRange externalArgs = op.externalArgs();
if (!externalArgs.empty())
p << "(" << externalArgs << " : " << externalArgs.getTypes() << ")";
} else {
p.printRegion(op.body(), /*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/false);
}

p.printOptionalAttrDictWithKeyword(op.getAttrs(),
{"name", "externalConstParams"});
}

static LogicalResult verify(RewriteOp op) {
Region &rewriteRegion = op.body();

Expand Down
6 changes: 6 additions & 0 deletions mlir/lib/IR/OperationSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ void OperationState::addRegion(std::unique_ptr<Region> &&region) {
regions.push_back(std::move(region));
}

void OperationState::addRegions(
MutableArrayRef<std::unique_ptr<Region>> regions) {
for (std::unique_ptr<Region> &region : regions)
addRegion(std::move(region));
}

//===----------------------------------------------------------------------===//
// OperandStorage
//===----------------------------------------------------------------------===//
Expand Down
5 changes: 3 additions & 2 deletions mlir/lib/Parser/AttributeParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ OptionalParseResult Parser::parseOptionalAttribute(Attribute &attribute,
return result;
}
}
OptionalParseResult Parser::parseOptionalAttribute(ArrayAttr &attribute) {
return parseOptionalAttributeWithToken(Token::l_square, attribute);
OptionalParseResult Parser::parseOptionalAttribute(ArrayAttr &attribute,
Type type) {
return parseOptionalAttributeWithToken(Token::l_square, attribute, type);
}

/// Attribute dictionary.
Expand Down
32 changes: 19 additions & 13 deletions mlir/lib/Parser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,6 @@ class CustomOpAsmParser : public OpAsmParser {
}

/// Parse an optional attribute.
/// Template utilities to simplify specifying multiple derived overloads.
template <typename AttrT>
OptionalParseResult
parseOptionalAttributeAndAddToList(AttrT &result, Type type,
Expand All @@ -1056,25 +1055,15 @@ class CustomOpAsmParser : public OpAsmParser {
attrs.push_back(parser.builder.getNamedAttr(attrName, result));
return parseResult;
}
template <typename AttrT>
OptionalParseResult parseOptionalAttributeAndAddToList(AttrT &result,
StringRef attrName,
NamedAttrList &attrs) {
OptionalParseResult parseResult = parser.parseOptionalAttribute(result);
if (parseResult.hasValue() && succeeded(*parseResult))
attrs.push_back(parser.builder.getNamedAttr(attrName, result));
return parseResult;
}

OptionalParseResult parseOptionalAttribute(Attribute &result, Type type,
StringRef attrName,
NamedAttrList &attrs) override {
return parseOptionalAttributeAndAddToList(result, type, attrName, attrs);
}
OptionalParseResult parseOptionalAttribute(ArrayAttr &result,
OptionalParseResult parseOptionalAttribute(ArrayAttr &result, Type type,
StringRef attrName,
NamedAttrList &attrs) override {
return parseOptionalAttributeAndAddToList(result, attrName, attrs);
return parseOptionalAttributeAndAddToList(result, type, attrName, attrs);
}

/// Parse a named dictionary into 'result' if it is present.
Expand Down Expand Up @@ -1355,6 +1344,23 @@ class CustomOpAsmParser : public OpAsmParser {
return parseRegion(region, arguments, argTypes, enableNameShadowing);
}

/// Parses a region if present. If the region is present, a new region is
/// allocated and placed in `region`. If no region is present, `region`
/// remains untouched.
OptionalParseResult
parseOptionalRegion(std::unique_ptr<Region> &region,
ArrayRef<OperandType> arguments, ArrayRef<Type> argTypes,
bool enableNameShadowing = false) override {
if (parser.getToken().isNot(Token::l_brace))
return llvm::None;
std::unique_ptr<Region> newRegion = std::make_unique<Region>();
if (parseRegion(*newRegion, arguments, argTypes, enableNameShadowing))
return failure();

region = std::move(newRegion);
return success();
}

/// Parse a region argument. The type of the argument will be resolved later
/// by a call to `parseRegion`.
ParseResult parseRegionArgument(OperandType &argument) override {
Expand Down
6 changes: 3 additions & 3 deletions mlir/lib/Parser/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class Parser {
/// Parse an optional attribute with the provided type.
OptionalParseResult parseOptionalAttribute(Attribute &attribute,
Type type = {});
OptionalParseResult parseOptionalAttribute(ArrayAttr &attribute);
OptionalParseResult parseOptionalAttribute(ArrayAttr &attribute, Type type);

/// Parse an optional attribute that is demarcated by a specific token.
template <typename AttributeT>
Expand All @@ -197,8 +197,8 @@ class Parser {
if (getToken().isNot(kind))
return llvm::None;

if (Attribute parsedAttr = parseAttribute()) {
attr = parsedAttr.cast<ArrayAttr>();
if (Attribute parsedAttr = parseAttribute(type)) {
attr = parsedAttr.cast<AttributeT>();
return success();
}
return failure();
Expand Down
124 changes: 124 additions & 0 deletions mlir/test/lib/Dialect/Test/TestDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,130 @@ void FoldToCallOp::getCanonicalizationPatterns(
results.insert<FoldToCallOpPattern>(context);
}

//===----------------------------------------------------------------------===//
// Test Format* operations
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Parsing

static ParseResult parseCustomDirectiveOperands(
OpAsmParser &parser, OpAsmParser::OperandType &operand,
Optional<OpAsmParser::OperandType> &optOperand,
SmallVectorImpl<OpAsmParser::OperandType> &varOperands) {
if (parser.parseOperand(operand))
return failure();
if (succeeded(parser.parseOptionalComma())) {
optOperand.emplace();
if (parser.parseOperand(*optOperand))
return failure();
}
if (parser.parseArrow() || parser.parseLParen() ||
parser.parseOperandList(varOperands) || parser.parseRParen())
return failure();
return success();
}
static ParseResult
parseCustomDirectiveResults(OpAsmParser &parser, Type &operandType,
Type &optOperandType,
SmallVectorImpl<Type> &varOperandTypes) {
if (parser.parseColon())
return failure();

if (parser.parseType(operandType))
return failure();
if (succeeded(parser.parseOptionalComma())) {
if (parser.parseType(optOperandType))
return failure();
}
if (parser.parseArrow() || parser.parseLParen() ||
parser.parseTypeList(varOperandTypes) || parser.parseRParen())
return failure();
return success();
}
static ParseResult parseCustomDirectiveOperandsAndTypes(
OpAsmParser &parser, OpAsmParser::OperandType &operand,
Optional<OpAsmParser::OperandType> &optOperand,
SmallVectorImpl<OpAsmParser::OperandType> &varOperands, Type &operandType,
Type &optOperandType, SmallVectorImpl<Type> &varOperandTypes) {
if (parseCustomDirectiveOperands(parser, operand, optOperand, varOperands) ||
parseCustomDirectiveResults(parser, operandType, optOperandType,
varOperandTypes))
return failure();
return success();
}
static ParseResult parseCustomDirectiveRegions(
OpAsmParser &parser, Region &region,
SmallVectorImpl<std::unique_ptr<Region>> &varRegions) {
if (parser.parseRegion(region))
return failure();
if (failed(parser.parseOptionalComma()))
return success();
std::unique_ptr<Region> varRegion = std::make_unique<Region>();
if (parser.parseRegion(*varRegion))
return failure();
varRegions.emplace_back(std::move(varRegion));
return success();
}
static ParseResult
parseCustomDirectiveSuccessors(OpAsmParser &parser, Block *&successor,
SmallVectorImpl<Block *> &varSuccessors) {
if (parser.parseSuccessor(successor))
return failure();
if (failed(parser.parseOptionalComma()))
return success();
Block *varSuccessor;
if (parser.parseSuccessor(varSuccessor))
return failure();
varSuccessors.append(2, varSuccessor);
return success();
}

//===----------------------------------------------------------------------===//
// Printing

static void printCustomDirectiveOperands(OpAsmPrinter &printer, Value operand,
Value optOperand,
OperandRange varOperands) {
printer << operand;
if (optOperand)
printer << ", " << optOperand;
printer << " -> (" << varOperands << ")";
}
static void printCustomDirectiveResults(OpAsmPrinter &printer, Type operandType,
Type optOperandType,
TypeRange varOperandTypes) {
printer << " : " << operandType;
if (optOperandType)
printer << ", " << optOperandType;
printer << " -> (" << varOperandTypes << ")";
}
static void
printCustomDirectiveOperandsAndTypes(OpAsmPrinter &printer, Value operand,
Value optOperand, OperandRange varOperands,
Type operandType, Type optOperandType,
TypeRange varOperandTypes) {
printCustomDirectiveOperands(printer, operand, optOperand, varOperands);
printCustomDirectiveResults(printer, operandType, optOperandType,
varOperandTypes);
}
static void printCustomDirectiveRegions(OpAsmPrinter &printer, Region &region,
MutableArrayRef<Region> varRegions) {
printer.printRegion(region);
if (!varRegions.empty()) {
printer << ", ";
for (Region &region : varRegions)
printer.printRegion(region);
}
}
static void printCustomDirectiveSuccessors(OpAsmPrinter &printer,
Block *successor,
SuccessorRange varSuccessors) {
printer << successor;
if (!varSuccessors.empty())
printer << ", " << varSuccessors.front();
}

//===----------------------------------------------------------------------===//
// Test IsolatedRegionOp - parse passthrough region arguments.
//===----------------------------------------------------------------------===//
Expand Down
123 changes: 119 additions & 4 deletions mlir/test/lib/Dialect/Test/TestOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1161,8 +1161,13 @@ def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> {
//===----------------------------------------------------------------------===//

def TestRegionBuilderOp : TEST_Op<"region_builder">;
def TestReturnOp : TEST_Op<"return", [ReturnLike, Terminator]>,
Arguments<(ins Variadic<AnyType>)>;
def TestReturnOp : TEST_Op<"return", [ReturnLike, Terminator]> {
let arguments = (ins Variadic<AnyType>);
let builders = [
OpBuilder<"OpBuilder &builder, OperationState &state",
[{ build(builder, state, {}); }]>
];
}
def TestCastOp : TEST_Op<"cast">,
Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>;
def TestInvalidOp : TEST_Op<"invalid", [Terminator]>,
Expand Down Expand Up @@ -1308,6 +1313,18 @@ def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> {
let assemblyFormat = "($opt_attr^)? attr-dict";
}

// Test that we format symbol name attributes properly.
def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> {
let arguments = (ins SymbolNameAttr:$attr);
let assemblyFormat = "$attr attr-dict";
}

// Test that we format optional symbol name attributes properly.
def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> {
let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr);
let assemblyFormat = "($opt_attr^)? attr-dict";
}

// Test that we elide attributes that are within the syntax.
def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> {
let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr);
Expand All @@ -1321,6 +1338,43 @@ def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> {
let assemblyFormat = "$buildable attr-dict";
}

// Test various mixings of region formatting.
class FormatRegionBase<string suffix, string fmt>
: TEST_Op<"format_region_" # suffix # "_op"> {
let regions = (region AnyRegion:$region);
let assemblyFormat = fmt;
}
def FormatRegionAOp : FormatRegionBase<"a", [{
regions attr-dict
}]>;
def FormatRegionBOp : FormatRegionBase<"b", [{
$region attr-dict
}]>;
def FormatRegionCOp : FormatRegionBase<"c", [{
(`region` $region^)? attr-dict
}]>;
class FormatVariadicRegionBase<string suffix, string fmt>
: TEST_Op<"format_variadic_region_" # suffix # "_op"> {
let regions = (region VariadicRegion<AnyRegion>:$regions);
let assemblyFormat = fmt;
}
def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{
$regions attr-dict
}]>;
def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{
($regions^ `found_regions`)? attr-dict
}]>;
class FormatRegionImplicitTerminatorBase<string suffix, string fmt>
: TEST_Op<"format_implicit_terminator_region_" # suffix # "_op",
[SingleBlockImplicitTerminator<"TestReturnOp">]> {
let regions = (region AnyRegion:$region);
let assemblyFormat = fmt;
}
def FormatFormatRegionImplicitTerminatorAOp
: FormatRegionImplicitTerminatorBase<"a", [{
$region attr-dict
}]>;

// Test various mixings of result type formatting.
class FormatResultBase<string suffix, string fmt>
: TEST_Op<"format_result_" # suffix # "_op"> {
Expand Down Expand Up @@ -1414,8 +1468,70 @@ def FormatOptionalUnitAttrNoElide
}

//===----------------------------------------------------------------------===//
// AllTypesMatch type inference
// Custom Directives

def FormatCustomDirectiveOperands
: TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> {
let arguments = (ins I64:$operand, Optional<I64>:$optOperand,
Variadic<I64>:$varOperands);
let assemblyFormat = [{
custom<CustomDirectiveOperands>(
$operand, $optOperand, $varOperands
)
attr-dict
}];
}

def FormatCustomDirectiveOperandsAndTypes
: TEST_Op<"format_custom_directive_operands_and_types",
[AttrSizedOperandSegments]> {
let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand,
Variadic<AnyType>:$varOperands);
let assemblyFormat = [{
custom<CustomDirectiveOperandsAndTypes>(
$operand, $optOperand, $varOperands,
type($operand), type($optOperand), type($varOperands)
)
attr-dict
}];
}

def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> {
let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$regions);
let assemblyFormat = [{
custom<CustomDirectiveRegions>(
$region, $regions
)
attr-dict
}];
}

def FormatCustomDirectiveResults
: TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> {
let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
Variadic<AnyType>:$varResults);
let assemblyFormat = [{
custom<CustomDirectiveResults>(
type($result), type($optResult), type($varResults)
)
attr-dict
}];
}

def FormatCustomDirectiveSuccessors
: TEST_Op<"format_custom_directive_successors", [Terminator]> {
let successors = (successor AnySuccessor:$successor,
VariadicSuccessor<AnySuccessor>:$successors);
let assemblyFormat = [{
custom<CustomDirectiveSuccessors>(
$successor, $successors
)
attr-dict
}];
}

//===----------------------------------------------------------------------===//
// AllTypesMatch type inference

def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [
AllTypesMatch<["value1", "value2", "result"]>
Expand All @@ -1435,7 +1551,6 @@ def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [

//===----------------------------------------------------------------------===//
// TypesMatchWith type inference
//===----------------------------------------------------------------------===//

def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [
TypesMatchWith<"result type matches operand", "value", "result", "$_self">
Expand Down
101 changes: 97 additions & 4 deletions mlir/test/mlir-tblgen/op-format-spec.td
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,49 @@ def DirectiveAttrDictValidB : TestFormat_Op<"attrdict_valid_b", [{
attr-dict-with-keyword
}]>;

//===----------------------------------------------------------------------===//
// custom

// CHECK: error: expected '<' before custom directive name
def DirectiveCustomInvalidA : TestFormat_Op<"custom_invalid_a", [{
custom(
}]>;
// CHECK: error: expected custom directive name identifier
def DirectiveCustomInvalidB : TestFormat_Op<"custom_invalid_b", [{
custom<>
}]>;
// CHECK: error: expected '>' after custom directive name
def DirectiveCustomInvalidC : TestFormat_Op<"custom_invalid_c", [{
custom<MyDirective(
}]>;
// CHECK: error: expected '(' before custom directive parameters
def DirectiveCustomInvalidD : TestFormat_Op<"custom_invalid_d", [{
custom<MyDirective>)
}]>;
// CHECK: error: only variables and types may be used as parameters to a custom directive
def DirectiveCustomInvalidE : TestFormat_Op<"custom_invalid_e", [{
custom<MyDirective>(operands)
}]>;
// CHECK: error: expected ')' after custom directive parameters
def DirectiveCustomInvalidF : TestFormat_Op<"custom_invalid_f", [{
custom<MyDirective>($operand<
}]>, Arguments<(ins I64:$operand)>;
// CHECK: error: type directives within a custom directive may only refer to variables
def DirectiveCustomInvalidH : TestFormat_Op<"custom_invalid_h", [{
custom<MyDirective>(type(operands))
}]>;

// CHECK-NOT: error
def DirectiveCustomValidA : TestFormat_Op<"custom_valid_a", [{
custom<MyDirective>($operand) attr-dict
}]>, Arguments<(ins Optional<I64>:$operand)>;
def DirectiveCustomValidB : TestFormat_Op<"custom_valid_b", [{
custom<MyDirective>($operand, type($operand), type($result)) attr-dict
}]>, Arguments<(ins I64:$operand)>, Results<(outs I64:$result)>;
def DirectiveCustomValidC : TestFormat_Op<"custom_valid_c", [{
custom<MyDirective>($attr) attr-dict
}]>, Arguments<(ins I64Attr:$attr)>;

//===----------------------------------------------------------------------===//
// functional-type

Expand Down Expand Up @@ -90,6 +133,28 @@ def DirectiveOperandsValid : TestFormat_Op<"operands_valid", [{
operands attr-dict
}]>;

//===----------------------------------------------------------------------===//
// regions

// CHECK: error: 'regions' directive creates overlap in format
def DirectiveRegionsInvalidA : TestFormat_Op<"regions_invalid_a", [{
regions regions attr-dict
}]>;
// CHECK: error: 'regions' directive creates overlap in format
def DirectiveRegionsInvalidB : TestFormat_Op<"regions_invalid_b", [{
$region regions attr-dict
}]> {
let regions = (region AnyRegion:$region);
}
// CHECK: error: 'regions' is only valid as a top-level directive
def DirectiveRegionsInvalidC : TestFormat_Op<"regions_invalid_c", [{
type(regions)
}]>;
// CHECK-NOT: error:
def DirectiveRegionsValid : TestFormat_Op<"regions_valid", [{
regions attr-dict
}]>;

//===----------------------------------------------------------------------===//
// results

Expand Down Expand Up @@ -206,7 +271,7 @@ def OptionalInvalidB : TestFormat_Op<"optional_invalid_b", [{
def OptionalInvalidC : TestFormat_Op<"optional_invalid_c", [{
($attr)? attr-dict
}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
// CHECK: error: first element of an operand group must be an attribute, literal, or operand
// CHECK: error: first element of an operand group must be an attribute, literal, operand, or region
def OptionalInvalidD : TestFormat_Op<"optional_invalid_d", [{
(type($operand) $operand^)? attr-dict
}]>, Arguments<(ins Optional<I64>:$operand)>;
Expand Down Expand Up @@ -238,12 +303,16 @@ def OptionalInvalidJ : TestFormat_Op<"optional_invalid_j", [{
def OptionalInvalidK : TestFormat_Op<"optional_invalid_k", [{
($arg^)
}]>, Arguments<(ins Variadic<I64>:$arg)>;
// CHECK: error: only variables can be used to anchor an optional group
def OptionalInvalidL : TestFormat_Op<"optional_invalid_l", [{
(custom<MyDirective>($arg)^)?
}]>, Arguments<(ins I64:$arg)>;

//===----------------------------------------------------------------------===//
// Variables
//===----------------------------------------------------------------------===//

// CHECK: error: expected variable to refer to an argument, result, or successor
// CHECK: error: expected variable to refer to an argument, region, result, or successor
def VariableInvalidA : TestFormat_Op<"variable_invalid_a", [{
$unknown_arg attr-dict
}]>;
Expand Down Expand Up @@ -283,11 +352,35 @@ def VariableInvalidH : TestFormat_Op<"variable_invalid_h", [{
def VariableInvalidI : TestFormat_Op<"variable_invalid_i", [{
(`foo` $attr^)? `:` attr-dict
}]>, Arguments<(ins OptionalAttr<ElementsAttr>:$attr)>;
// CHECK-NOT: error:
// CHECK: error: region 'region' is already bound
def VariableInvalidJ : TestFormat_Op<"variable_invalid_j", [{
$region $region attr-dict
}]> {
let regions = (region AnyRegion:$region);
}
// CHECK: error: region 'region' is already bound
def VariableInvalidK : TestFormat_Op<"variable_invalid_K", [{
regions $region attr-dict
}]> {
let regions = (region AnyRegion:$region);
}
// CHECK: error: regions can only be used at the top level
def VariableInvalidL : TestFormat_Op<"variable_invalid_l", [{
type($region)
}]> {
let regions = (region AnyRegion:$region);
}
// CHECK: error: region #0, named 'region', not found
def VariableInvalidM : TestFormat_Op<"variable_invalid_m", [{
attr-dict
}]> {
let regions = (region AnyRegion:$region);
}
// CHECK-NOT: error:
def VariableValidA : TestFormat_Op<"variable_valid_a", [{
$attr `:` attr-dict
}]>, Arguments<(ins OptionalAttr<I1Attr>:$attr)>;
def VariableInvalidK : TestFormat_Op<"variable_invalid_k", [{
def VariableValidB : TestFormat_Op<"variable_valid_b", [{
(`foo` $attr^)? `:` attr-dict
}]>, Arguments<(ins OptionalAttr<I1Attr>:$attr)>;

Expand Down
127 changes: 127 additions & 0 deletions mlir/test/mlir-tblgen/op-format.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ test.format_opt_attr_op_a
test.format_opt_attr_op_b 10
test.format_opt_attr_op_b

// CHECK: test.format_symbol_name_attr_op @name
// CHECK-NOT: {attr
test.format_symbol_name_attr_op @name

// CHECK: test.format_symbol_name_attr_op @opt_name
// CHECK-NOT: {attr
test.format_symbol_name_attr_op @opt_name
test.format_opt_symbol_name_attr_op

// CHECK: test.format_attr_dict_w_keyword attributes {attr = 10 : i64}
test.format_attr_dict_w_keyword attributes {attr = 10 : i64}

Expand All @@ -31,6 +40,72 @@ test.format_attr_dict_w_keyword attributes {attr = 10 : i64, opt_attr = 10 : i64
// CHECK: test.format_buildable_type_op %[[I64]]
%ignored = test.format_buildable_type_op %i64

//===----------------------------------------------------------------------===//
// Format regions
//===----------------------------------------------------------------------===//

// CHECK: test.format_region_a_op {
// CHECK-NEXT: test.return
test.format_region_a_op {
"test.return"() : () -> ()
}

// CHECK: test.format_region_b_op {
// CHECK-NEXT: test.return
test.format_region_b_op {
"test.return"() : () -> ()
}

// CHECK: test.format_region_c_op region {
// CHECK-NEXT: test.return
test.format_region_c_op region {
"test.return"() : () -> ()
}
// CHECK: test.format_region_c_op
// CHECK-NOT: region {
test.format_region_c_op

// CHECK: test.format_variadic_region_a_op {
// CHECK-NEXT: test.return
// CHECK-NEXT: }, {
// CHECK-NEXT: test.return
// CHECK-NEXT: }
test.format_variadic_region_a_op {
"test.return"() : () -> ()
}, {
"test.return"() : () -> ()
}
// CHECK: test.format_variadic_region_b_op {
// CHECK-NEXT: test.return
// CHECK-NEXT: }, {
// CHECK-NEXT: test.return
// CHECK-NEXT: } found_regions
test.format_variadic_region_b_op {
"test.return"() : () -> ()
}, {
"test.return"() : () -> ()
} found_regions
// CHECK: test.format_variadic_region_b_op
// CHECK-NOT: {
// CHECK-NOT: found_regions
test.format_variadic_region_b_op

// CHECK: test.format_implicit_terminator_region_a_op {
// CHECK-NEXT: }
test.format_implicit_terminator_region_a_op {
"test.return"() : () -> ()
}
// CHECK: test.format_implicit_terminator_region_a_op {
// CHECK-NEXT: test.return"() {foo.attr
test.format_implicit_terminator_region_a_op {
"test.return"() {foo.attr} : () -> ()
}
// CHECK: test.format_implicit_terminator_region_a_op {
// CHECK-NEXT: test.return"(%[[I64]]) : (i64)
test.format_implicit_terminator_region_a_op {
"test.return"(%i64) : (i64) -> ()
}

//===----------------------------------------------------------------------===//
// Format results
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -122,6 +197,58 @@ test.format_optional_operand_result_b_op( : ) : i64
// CHECK: test.format_optional_operand_result_b_op : i64
test.format_optional_operand_result_b_op : i64

//===----------------------------------------------------------------------===//
// Format custom directives
//===----------------------------------------------------------------------===//

// CHECK: test.format_custom_directive_operands %[[I64]], %[[I64]] -> (%[[I64]])
test.format_custom_directive_operands %i64, %i64 -> (%i64)

// CHECK: test.format_custom_directive_operands %[[I64]] -> (%[[I64]])
test.format_custom_directive_operands %i64 -> (%i64)

// CHECK: test.format_custom_directive_operands_and_types %[[I64]], %[[I64]] -> (%[[I64]]) : i64, i64 -> (i64)
test.format_custom_directive_operands_and_types %i64, %i64 -> (%i64) : i64, i64 -> (i64)

// CHECK: test.format_custom_directive_operands_and_types %[[I64]] -> (%[[I64]]) : i64 -> (i64)
test.format_custom_directive_operands_and_types %i64 -> (%i64) : i64 -> (i64)

// CHECK: test.format_custom_directive_regions {
// CHECK-NEXT: test.return
// CHECK-NEXT: }
test.format_custom_directive_regions {
"test.return"() : () -> ()
}

// CHECK: test.format_custom_directive_regions {
// CHECK-NEXT: test.return
// CHECK-NEXT: }, {
// CHECK-NEXT: test.return
// CHECK-NEXT: }
test.format_custom_directive_regions {
"test.return"() : () -> ()
}, {
"test.return"() : () -> ()
}

// CHECK: test.format_custom_directive_results : i64, i64 -> (i64)
test.format_custom_directive_results : i64, i64 -> (i64)

// CHECK: test.format_custom_directive_results : i64 -> (i64)
test.format_custom_directive_results : i64 -> (i64)

func @foo() {
// CHECK: test.format_custom_directive_successors ^bb1, ^bb2
test.format_custom_directive_successors ^bb1, ^bb2

^bb1:
// CHECK: test.format_custom_directive_successors ^bb2
test.format_custom_directive_successors ^bb2

^bb2:
return
}

//===----------------------------------------------------------------------===//
// Format trait type inference
//===----------------------------------------------------------------------===//
Expand Down
791 changes: 685 additions & 106 deletions mlir/tools/mlir-tblgen/OpFormatGen.cpp

Large diffs are not rendered by default.