llvm-project/mlir/test/mlir-tblgen/op-format-spec.td

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

335 lines
14 KiB
TableGen
Raw Normal View History

// RUN: mlir-tblgen -gen-op-decls -asmformat-error-is-fatal=false -I %S/../../include %s 2>&1 | FileCheck %s --dump-input-on-failure
// This file contains tests for the specification of the declarative op format.
include "mlir/IR/OpBase.td"
def TestDialect : Dialect {
let name = "test";
}
class TestFormat_Op<string name, string fmt, list<OpTrait> traits = []>
: Op<TestDialect, name, traits> {
let assemblyFormat = fmt;
}
//===----------------------------------------------------------------------===//
// Directives
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// attr-dict
// CHECK: error: format missing 'attr-dict' directive
def DirectiveAttrDictInvalidA : TestFormat_Op<"attrdict_invalid_a", [{
}]>;
// CHECK: error: 'attr-dict' directive has already been seen
def DirectiveAttrDictInvalidB : TestFormat_Op<"attrdict_invalid_b", [{
attr-dict attr-dict
}]>;
// CHECK: error: 'attr-dict' directive has already been seen
def DirectiveAttrDictInvalidC : TestFormat_Op<"attrdict_invalid_c", [{
attr-dict attr-dict-with-keyword
}]>;
// CHECK: error: 'attr-dict' directive can only be used as a top-level directive
def DirectiveAttrDictInvalidD : TestFormat_Op<"attrdict_invalid_d", [{
type(attr-dict)
}]>;
// CHECK-NOT: error
def DirectiveAttrDictValidA : TestFormat_Op<"attrdict_valid_a", [{
attr-dict
}]>;
def DirectiveAttrDictValidB : TestFormat_Op<"attrdict_valid_b", [{
attr-dict-with-keyword
}]>;
//===----------------------------------------------------------------------===//
// functional-type
// CHECK: error: 'functional-type' is only valid as a top-level directive
def DirectiveFunctionalTypeInvalidA : TestFormat_Op<"functype_invalid_a", [{
functional-type(functional-type)
}]>;
// CHECK: error: expected '(' before argument list
def DirectiveFunctionalTypeInvalidB : TestFormat_Op<"functype_invalid_b", [{
functional-type
}]>;
[mlir][DeclarativeParser] Add basic support for optional groups in the assembly format. When operations have optional attributes, or optional operands(i.e. empty variadic operands), the assembly format often has an optional section to represent these arguments. This revision adds basic support for defining an "optional group" in the assembly format to support this. An optional group is defined by wrapping a set of elements in `()` followed by `?` and requires the following: * The first element of the group must be either a literal or an operand argument. - This is because the first element must be optionally parsable. * There must be exactly one argument variable within the group that is marked as the anchor of the group. The anchor is the element whose presence controls whether the group should be printed/parsed. An element is marked as the anchor by adding a trailing `^`. * The group must only contain literals, variables, and type directives. - Any attribute variables may be used, but only optional attributes can be marked as the anchor. - Only variadic, i.e. optional, operand arguments can be used. - The elements of a type directive must be defined within the same optional group. An example of this can be seen with the assembly format for ReturnOp, which has a variadic number of operands. ``` def ReturnOp : ... { let arguments = (ins Variadic<AnyType>:$operands); // We only print the operands+types if there are a non-zero number // of operands. let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; } ``` Differential Revision: https://reviews.llvm.org/D74681
2020-02-22 05:19:15 +08:00
// CHECK: error: expected directive, literal, variable, or optional group
def DirectiveFunctionalTypeInvalidC : TestFormat_Op<"functype_invalid_c", [{
functional-type(
}]>;
// CHECK: error: expected ',' after inputs argument
def DirectiveFunctionalTypeInvalidD : TestFormat_Op<"functype_invalid_d", [{
functional-type(operands
}]>;
[mlir][DeclarativeParser] Add basic support for optional groups in the assembly format. When operations have optional attributes, or optional operands(i.e. empty variadic operands), the assembly format often has an optional section to represent these arguments. This revision adds basic support for defining an "optional group" in the assembly format to support this. An optional group is defined by wrapping a set of elements in `()` followed by `?` and requires the following: * The first element of the group must be either a literal or an operand argument. - This is because the first element must be optionally parsable. * There must be exactly one argument variable within the group that is marked as the anchor of the group. The anchor is the element whose presence controls whether the group should be printed/parsed. An element is marked as the anchor by adding a trailing `^`. * The group must only contain literals, variables, and type directives. - Any attribute variables may be used, but only optional attributes can be marked as the anchor. - Only variadic, i.e. optional, operand arguments can be used. - The elements of a type directive must be defined within the same optional group. An example of this can be seen with the assembly format for ReturnOp, which has a variadic number of operands. ``` def ReturnOp : ... { let arguments = (ins Variadic<AnyType>:$operands); // We only print the operands+types if there are a non-zero number // of operands. let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; } ``` Differential Revision: https://reviews.llvm.org/D74681
2020-02-22 05:19:15 +08:00
// CHECK: error: expected directive, literal, variable, or optional group
def DirectiveFunctionalTypeInvalidE : TestFormat_Op<"functype_invalid_e", [{
functional-type(operands,
}]>;
// CHECK: error: expected ')' after argument list
def DirectiveFunctionalTypeInvalidF : TestFormat_Op<"functype_invalid_f", [{
functional-type(operands, results
}]>;
// CHECK-NOT: error
def DirectiveFunctionalTypeValid : TestFormat_Op<"functype_invalid_a", [{
functional-type(operands, results) attr-dict
}]>;
//===----------------------------------------------------------------------===//
// operands
// CHECK: error: 'operands' directive creates overlap in format
def DirectiveOperandsInvalidA : TestFormat_Op<"operands_invalid_a", [{
operands operands
}]>;
// CHECK: error: 'operands' directive creates overlap in format
def DirectiveOperandsInvalidB : TestFormat_Op<"operands_invalid_b", [{
$operand operands
}]>, Arguments<(ins I64:$operand)>;
// CHECK-NOT: error:
def DirectiveOperandsValid : TestFormat_Op<"operands_valid", [{
operands attr-dict
}]>;
//===----------------------------------------------------------------------===//
// results
// CHECK: error: 'results' directive can not be used as a top-level directive
def DirectiveResultsInvalidA : TestFormat_Op<"results_invalid_a", [{
results
}]>;
//===----------------------------------------------------------------------===//
// successors
// CHECK: error: 'successors' is only valid as a top-level directive
def DirectiveSuccessorsInvalidA : TestFormat_Op<"successors_invalid_a", [{
type(successors)
}]>;
//===----------------------------------------------------------------------===//
// type
// CHECK: error: expected '(' before argument list
def DirectiveTypeInvalidA : TestFormat_Op<"type_invalid_a", [{
type
}]>;
[mlir][DeclarativeParser] Add basic support for optional groups in the assembly format. When operations have optional attributes, or optional operands(i.e. empty variadic operands), the assembly format often has an optional section to represent these arguments. This revision adds basic support for defining an "optional group" in the assembly format to support this. An optional group is defined by wrapping a set of elements in `()` followed by `?` and requires the following: * The first element of the group must be either a literal or an operand argument. - This is because the first element must be optionally parsable. * There must be exactly one argument variable within the group that is marked as the anchor of the group. The anchor is the element whose presence controls whether the group should be printed/parsed. An element is marked as the anchor by adding a trailing `^`. * The group must only contain literals, variables, and type directives. - Any attribute variables may be used, but only optional attributes can be marked as the anchor. - Only variadic, i.e. optional, operand arguments can be used. - The elements of a type directive must be defined within the same optional group. An example of this can be seen with the assembly format for ReturnOp, which has a variadic number of operands. ``` def ReturnOp : ... { let arguments = (ins Variadic<AnyType>:$operands); // We only print the operands+types if there are a non-zero number // of operands. let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; } ``` Differential Revision: https://reviews.llvm.org/D74681
2020-02-22 05:19:15 +08:00
// CHECK: error: expected directive, literal, variable, or optional group
def DirectiveTypeInvalidB : TestFormat_Op<"type_invalid_b", [{
type(
}]>;
// CHECK: error: expected ')' after argument list
def DirectiveTypeInvalidC : TestFormat_Op<"type_invalid_c", [{
type(operands
}]>;
// CHECK-NOT: error:
def DirectiveTypeValid : TestFormat_Op<"type_valid", [{
type(operands) attr-dict
}]>;
//===----------------------------------------------------------------------===//
// functional-type/type operands
// CHECK: error: 'type' directive operand expects variable or directive operand
def DirectiveTypeZOperandInvalidA : TestFormat_Op<"type_operand_invalid_a", [{
type(`literal`)
}]>;
// CHECK: error: 'operands' 'type' is already bound
def DirectiveTypeZOperandInvalidB : TestFormat_Op<"type_operand_invalid_b", [{
type(operands) type(operands)
}]>;
// CHECK: error: 'operands' 'type' is already bound
def DirectiveTypeZOperandInvalidC : TestFormat_Op<"type_operand_invalid_c", [{
type($operand) type(operands)
}]>, Arguments<(ins I64:$operand)>;
// CHECK: error: 'type' of 'operand' is already bound
def DirectiveTypeZOperandInvalidD : TestFormat_Op<"type_operand_invalid_d", [{
type(operands) type($operand)
}]>, Arguments<(ins I64:$operand)>;
// CHECK: error: 'type' of 'operand' is already bound
def DirectiveTypeZOperandInvalidE : TestFormat_Op<"type_operand_invalid_e", [{
type($operand) type($operand)
}]>, Arguments<(ins I64:$operand)>;
// CHECK: error: 'results' 'type' is already bound
def DirectiveTypeZOperandInvalidF : TestFormat_Op<"type_operand_invalid_f", [{
type(results) type(results)
}]>;
// CHECK: error: 'results' 'type' is already bound
def DirectiveTypeZOperandInvalidG : TestFormat_Op<"type_operand_invalid_g", [{
type($result) type(results)
}]>, Results<(outs I64:$result)>;
// CHECK: error: 'type' of 'result' is already bound
def DirectiveTypeZOperandInvalidH : TestFormat_Op<"type_operand_invalid_h", [{
type(results) type($result)
}]>, Results<(outs I64:$result)>;
// CHECK: error: 'type' of 'result' is already bound
def DirectiveTypeZOperandInvalidI : TestFormat_Op<"type_operand_invalid_i", [{
type($result) type($result)
}]>, Results<(outs I64:$result)>;
// CHECK-NOT: error:
def DirectiveTypeZOperandValid : TestFormat_Op<"type_operand_valid", [{
type(operands) type(results) attr-dict
}]>;
//===----------------------------------------------------------------------===//
// Literals
//===----------------------------------------------------------------------===//
// Test all of the valid literals.
// CHECK: error: expected valid literal
def LiteralInvalidA : TestFormat_Op<"literal_invalid_a", [{
`1`
}]>;
// CHECK: error: unexpected end of file in literal
[mlir][DeclarativeParser] Add basic support for optional groups in the assembly format. When operations have optional attributes, or optional operands(i.e. empty variadic operands), the assembly format often has an optional section to represent these arguments. This revision adds basic support for defining an "optional group" in the assembly format to support this. An optional group is defined by wrapping a set of elements in `()` followed by `?` and requires the following: * The first element of the group must be either a literal or an operand argument. - This is because the first element must be optionally parsable. * There must be exactly one argument variable within the group that is marked as the anchor of the group. The anchor is the element whose presence controls whether the group should be printed/parsed. An element is marked as the anchor by adding a trailing `^`. * The group must only contain literals, variables, and type directives. - Any attribute variables may be used, but only optional attributes can be marked as the anchor. - Only variadic, i.e. optional, operand arguments can be used. - The elements of a type directive must be defined within the same optional group. An example of this can be seen with the assembly format for ReturnOp, which has a variadic number of operands. ``` def ReturnOp : ... { let arguments = (ins Variadic<AnyType>:$operands); // We only print the operands+types if there are a non-zero number // of operands. let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; } ``` Differential Revision: https://reviews.llvm.org/D74681
2020-02-22 05:19:15 +08:00
// CHECK: error: expected directive, literal, variable, or optional group
def LiteralInvalidB : TestFormat_Op<"literal_invalid_b", [{
`
}]>;
// CHECK-NOT: error
def LiteralValid : TestFormat_Op<"literal_valid", [{
`_` `:` `,` `=` `<` `>` `(` `)` `[` `]` `->` `abc$._`
attr-dict
}]>;
[mlir][DeclarativeParser] Add basic support for optional groups in the assembly format. When operations have optional attributes, or optional operands(i.e. empty variadic operands), the assembly format often has an optional section to represent these arguments. This revision adds basic support for defining an "optional group" in the assembly format to support this. An optional group is defined by wrapping a set of elements in `()` followed by `?` and requires the following: * The first element of the group must be either a literal or an operand argument. - This is because the first element must be optionally parsable. * There must be exactly one argument variable within the group that is marked as the anchor of the group. The anchor is the element whose presence controls whether the group should be printed/parsed. An element is marked as the anchor by adding a trailing `^`. * The group must only contain literals, variables, and type directives. - Any attribute variables may be used, but only optional attributes can be marked as the anchor. - Only variadic, i.e. optional, operand arguments can be used. - The elements of a type directive must be defined within the same optional group. An example of this can be seen with the assembly format for ReturnOp, which has a variadic number of operands. ``` def ReturnOp : ... { let arguments = (ins Variadic<AnyType>:$operands); // We only print the operands+types if there are a non-zero number // of operands. let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; } ``` Differential Revision: https://reviews.llvm.org/D74681
2020-02-22 05:19:15 +08:00
//===----------------------------------------------------------------------===//
// Optional Groups
//===----------------------------------------------------------------------===//
// CHECK: error: optional groups can only be used as top-level elements
def OptionalInvalidA : TestFormat_Op<"optional_invalid_a", [{
type(($attr^)?) attr-dict
}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
// CHECK: error: expected directive, literal, variable, or optional group
def OptionalInvalidB : TestFormat_Op<"optional_invalid_b", [{
() attr-dict
}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
// CHECK: error: optional group specified no anchor element
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 a literal or operand
def OptionalInvalidD : TestFormat_Op<"optional_invalid_d", [{
($attr^)? attr-dict
}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
// CHECK: error: type directive can only refer to variables within the optional group
def OptionalInvalidE : TestFormat_Op<"optional_invalid_e", [{
(`,` $attr^ type(operands))? attr-dict
}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
// CHECK: error: only one element can be marked as the anchor of an optional group
def OptionalInvalidF : TestFormat_Op<"optional_invalid_f", [{
($attr^ $attr2^) attr-dict
}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr, OptionalAttr<I64Attr>:$attr2)>;
// CHECK: error: only optional attributes can be used to anchor an optional group
def OptionalInvalidG : TestFormat_Op<"optional_invalid_g", [{
($attr^) attr-dict
}]>, Arguments<(ins I64Attr:$attr)>;
// CHECK: error: only variadic operands can be used within an optional group
def OptionalInvalidH : TestFormat_Op<"optional_invalid_h", [{
($arg^) attr-dict
}]>, Arguments<(ins I64:$arg)>;
// CHECK: error: only variables can be used to anchor an optional group
def OptionalInvalidI : TestFormat_Op<"optional_invalid_i", [{
($arg type($arg)^) attr-dict
}]>, Arguments<(ins Variadic<I64>:$arg)>;
// CHECK: error: only literals, types, and variables can be used within an optional group
def OptionalInvalidJ : TestFormat_Op<"optional_invalid_j", [{
(attr-dict)
}]>;
// CHECK: error: expected '?' after optional group
def OptionalInvalidK : TestFormat_Op<"optional_invalid_k", [{
($arg^)
}]>, Arguments<(ins Variadic<I64>:$arg)>;
//===----------------------------------------------------------------------===//
// Variables
//===----------------------------------------------------------------------===//
// CHECK: error: expected variable to refer to a argument, result, or successor
def VariableInvalidA : TestFormat_Op<"variable_invalid_a", [{
$unknown_arg attr-dict
}]>;
// CHECK: error: attribute 'attr' is already bound
def VariableInvalidB : TestFormat_Op<"variable_invalid_b", [{
$attr $attr attr-dict
}]>, Arguments<(ins I64Attr:$attr)>;
// CHECK: error: operand 'operand' is already bound
def VariableInvalidC : TestFormat_Op<"variable_invalid_c", [{
$operand $operand attr-dict
}]>, Arguments<(ins I64:$operand)>;
// CHECK: error: operand 'operand' is already bound
def VariableInvalidD : TestFormat_Op<"variable_invalid_d", [{
operands $operand attr-dict
}]>, Arguments<(ins I64:$operand)>;
// CHECK: error: results can not be used at the top level
def VariableInvalidE : TestFormat_Op<"variable_invalid_e", [{
$result attr-dict
}]>, Results<(outs I64:$result)>;
// CHECK: error: successor 'successor' is already bound
def VariableInvalidF : TestFormat_Op<"variable_invalid_f", [{
$successor $successor attr-dict
}]> {
let successors = (successor AnySuccessor:$successor);
}
// CHECK: error: successor 'successor' is already bound
def VariableInvalidG : TestFormat_Op<"variable_invalid_g", [{
successors $successor attr-dict
}]> {
let successors = (successor AnySuccessor:$successor);
}
//===----------------------------------------------------------------------===//
// Coverage Checks
//===----------------------------------------------------------------------===//
// CHECK: error: format missing instance of result #0('result') type
def ZCoverageInvalidA : TestFormat_Op<"variable_invalid_a", [{
attr-dict
}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
// CHECK: error: format missing instance of operand #0('operand')
def ZCoverageInvalidB : TestFormat_Op<"variable_invalid_b", [{
type($result) attr-dict
}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
// CHECK: error: format missing instance of operand #0('operand') type
def ZCoverageInvalidC : TestFormat_Op<"variable_invalid_c", [{
$operand type($result) attr-dict
}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
// CHECK: error: format missing instance of operand #0('operand') type
def ZCoverageInvalidD : TestFormat_Op<"variable_invalid_d", [{
operands attr-dict
}]>, Arguments<(ins Variadic<I64>:$operand)>;
// CHECK: error: format missing instance of result #0('result') type
def ZCoverageInvalidE : TestFormat_Op<"variable_invalid_e", [{
attr-dict
}]>, Results<(outs Variadic<I64>:$result)>;
// CHECK-NOT: error
def ZCoverageValidA : TestFormat_Op<"variable_valid_a", [{
$operand type($operand) type($result) attr-dict
}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
def ZCoverageValidB : TestFormat_Op<"variable_valid_b", [{
$operand type(operands) type(results) attr-dict
}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
def ZCoverageValidC : TestFormat_Op<"variable_valid_c", [{
operands functional-type(operands, results) attr-dict
}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
// Check that we can infer type equalities from certain traits.
def ZCoverageValidD : TestFormat_Op<"variable_valid_d", [{
operands type($result) attr-dict
}], [SameOperandsAndResultType]>, Arguments<(ins AnyMemRef:$operand)>,
Results<(outs AnyMemRef:$result)>;
def ZCoverageValidE : TestFormat_Op<"variable_valid_e", [{
$operand type($operand) attr-dict
}], [SameOperandsAndResultType]>, Arguments<(ins AnyMemRef:$operand)>,
Results<(outs AnyMemRef:$result)>;
def ZCoverageValidF : TestFormat_Op<"variable_valid_f", [{
operands type($other) attr-dict
}], [SameTypeOperands]>, Arguments<(ins AnyMemRef:$operand, AnyMemRef:$other)>;
def ZCoverageValidG : TestFormat_Op<"variable_valid_g", [{
operands type($other) attr-dict
}], [AllTypesMatch<["operand", "other"]>]>,
Arguments<(ins AnyMemRef:$operand, AnyMemRef:$other)>;
def ZCoverageValidH : TestFormat_Op<"variable_valid_h", [{
operands type($result) attr-dict
}], [AllTypesMatch<["operand", "result"]>]>,
Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;