547 lines · plain
1// RUN: mlir-tblgen -gen-op-decls -asmformat-error-is-fatal=false -I %S/../../include %s -o=%t 2>&1 | FileCheck %s2 3// This file contains tests for the specification of the declarative op format.4 5include "mlir/IR/OpBase.td"6include "mlir/Interfaces/InferTypeOpInterface.td"7 8def TestDialect : Dialect {9 let name = "test";10}11class TestFormat_Op<string fmt, list<Trait> traits = []>12 : Op<TestDialect, "format_op", traits> {13 let assemblyFormat = fmt;14}15 16//===----------------------------------------------------------------------===//17// Directives18//===----------------------------------------------------------------------===//19 20//===----------------------------------------------------------------------===//21// attr-dict22//===----------------------------------------------------------------------===//23 24// CHECK: error: 'attr-dict' directive not found25def DirectiveAttrDictInvalidA : TestFormat_Op<[{26}]>;27// CHECK: error: 'attr-dict' directive has already been seen28def DirectiveAttrDictInvalidB : TestFormat_Op<[{29 attr-dict attr-dict30}]>;31// CHECK: error: 'attr-dict' directive has already been seen32def DirectiveAttrDictInvalidC : TestFormat_Op<[{33 attr-dict attr-dict-with-keyword34}]>;35// CHECK: error: 'attr-dict' directive can only be used as a top-level directive36def DirectiveAttrDictInvalidD : TestFormat_Op<[{37 type(attr-dict)38}]>;39 40//===----------------------------------------------------------------------===//41// custom42//===----------------------------------------------------------------------===//43 44// CHECK: error: expected '<' before custom directive name45def DirectiveCustomInvalidA : TestFormat_Op<[{46 custom(47}]>;48// CHECK: error: expected custom directive name identifier49def DirectiveCustomInvalidB : TestFormat_Op<[{50 custom<>51}]>;52// CHECK: error: expected '>' after custom directive name53def DirectiveCustomInvalidC : TestFormat_Op<[{54 custom<MyDirective(55}]>;56// CHECK: error: expected '(' before custom directive parameters57def DirectiveCustomInvalidD : TestFormat_Op<[{58 custom<MyDirective>)59}]>;60// CHECK: error: only variables and types may be used as parameters to a custom directive61def DirectiveCustomInvalidE : TestFormat_Op<[{62 custom<MyDirective>(operands)63}]>;64// CHECK: error: expected ')' after custom directive parameters65def DirectiveCustomInvalidF : TestFormat_Op<[{66 custom<MyDirective>($operand<67}]>, Arguments<(ins I64:$operand)>;68// CHECK: error: type directives within a custom directive may only refer to variables69def DirectiveCustomInvalidH : TestFormat_Op<[{70 custom<MyDirective>(type(operands))71}]>;72 73//===----------------------------------------------------------------------===//74// functional-type75//===----------------------------------------------------------------------===//76 77// CHECK: error: 'functional-type' is only valid as a top-level directive78def DirectiveFunctionalTypeInvalidA : TestFormat_Op<[{79 functional-type(functional-type)80}]>;81// CHECK: error: expected '(' before argument list82def DirectiveFunctionalTypeInvalidB : TestFormat_Op<[{83 functional-type84}]>;85// CHECK: error: expected literal, variable, directive, or optional group86def DirectiveFunctionalTypeInvalidC : TestFormat_Op<[{87 functional-type(88}]>;89// CHECK: error: expected ',' after inputs argument90def DirectiveFunctionalTypeInvalidD : TestFormat_Op<[{91 functional-type(operands92}]>;93// CHECK: error: expected literal, variable, directive, or optional group94def DirectiveFunctionalTypeInvalidE : TestFormat_Op<[{95 functional-type(operands,96}]>;97// CHECK: error: expected ')' after argument list98def DirectiveFunctionalTypeInvalidF : TestFormat_Op<[{99 functional-type(operands, results100}]>;101 102//===----------------------------------------------------------------------===//103// operands104//===----------------------------------------------------------------------===//105 106// CHECK: error: 'operands' directive creates overlap in format107def DirectiveOperandsInvalidA : TestFormat_Op<[{108 operands operands109}]>;110// CHECK: error: 'operands' directive creates overlap in format111def DirectiveOperandsInvalidB : TestFormat_Op<[{112 $operand operands113}]>, Arguments<(ins I64:$operand)>;114 115//===----------------------------------------------------------------------===//116// ref117//===----------------------------------------------------------------------===//118 119// CHECK: error: 'ref' is only valid within a `custom` directive120def DirectiveRefInvalidA : TestFormat_Op<[{121 ref(type($operand))122}]>, Arguments<(ins I64:$operand)>;123 124// CHECK: error: 'ref' of 'type($operand)' is not bound by a prior 'type' directive125def DirectiveRefInvalidB : TestFormat_Op<[{126 custom<Foo>(ref(type($operand)))127}]>, Arguments<(ins I64:$operand)>;128 129// CHECK: error: 'ref' of 'type(operands)' is not bound by a prior 'type' directive130def DirectiveRefInvalidC : TestFormat_Op<[{131 custom<Foo>(ref(type(operands)))132}]>;133 134// CHECK: error: 'ref' of 'type($result)' is not bound by a prior 'type' directive135def DirectiveRefInvalidD : TestFormat_Op<[{136 custom<Foo>(ref(type($result)))137}]>, Results<(outs I64:$result)>;138 139// CHECK: error: 'ref' of 'type(results)' is not bound by a prior 'type' directive140def DirectiveRefInvalidE : TestFormat_Op<[{141 custom<Foo>(ref(type(results)))142}]>;143 144// CHECK: error: 'ref' of 'successors' is not bound by a prior 'successors' directive145def DirectiveRefInvalidF : TestFormat_Op<[{146 custom<Foo>(ref(successors))147}]>;148 149// CHECK: error: 'ref' of 'regions' is not bound by a prior 'regions' directive150def DirectiveRefInvalidG : TestFormat_Op<[{151 custom<Foo>(ref(regions))152}]>;153 154// CHECK: error: expected '(' before argument list155def DirectiveRefInvalidH : TestFormat_Op<[{156 custom<Foo>(ref)157}]>;158 159// CHECK: error: expected ')' after argument list160def DirectiveRefInvalidI : TestFormat_Op<[{161 operands custom<Foo>(ref(operands(162}]>;163 164// CHECK: error: 'ref' of 'operands' is not bound by a prior 'operands' directive165def DirectiveRefInvalidJ : TestFormat_Op<[{166 custom<Foo>(ref(operands))167}]>;168 169// CHECK: error: 'ref' of 'attr-dict' is not bound by a prior 'attr-dict' directive170def DirectiveRefInvalidK : TestFormat_Op<[{171 custom<Foo>(ref(attr-dict))172}]>;173 174// CHECK: error: successor 'successor' must be bound before it is referenced175def DirectiveRefInvalidL : TestFormat_Op<[{176 custom<Foo>(ref($successor))177}]> {178 let successors = (successor AnySuccessor:$successor);179}180 181// CHECK: error: region 'region' must be bound before it is referenced182def DirectiveRefInvalidM : TestFormat_Op<[{183 custom<Foo>(ref($region))184}]> {185 let regions = (region AnyRegion:$region);186}187 188// CHECK: error: attribute 'attr' must be bound before it is referenced189def DirectiveRefInvalidN : TestFormat_Op<[{190 custom<Foo>(ref($attr))191}]>, Arguments<(ins I64Attr:$attr)>;192 193 194// CHECK: error: operand 'operand' must be bound before it is referenced195def DirectiveRefInvalidO : TestFormat_Op<[{196 custom<Foo>(ref($operand))197}]>, Arguments<(ins I64:$operand)>;198 199//===----------------------------------------------------------------------===//200// regions201//===----------------------------------------------------------------------===//202 203// CHECK: error: 'regions' directive creates overlap in format204def DirectiveRegionsInvalidA : TestFormat_Op<[{205 regions regions attr-dict206}]>;207// CHECK: error: 'regions' directive creates overlap in format208def DirectiveRegionsInvalidB : TestFormat_Op<[{209 $region regions attr-dict210}]> {211 let regions = (region AnyRegion:$region);212}213// CHECK: error: 'regions' is only valid as a top-level directive214def DirectiveRegionsInvalidC : TestFormat_Op<[{215 type(regions)216}]>;217// CHECK: error: format ambiguity caused by `attr-dict` directive followed by region `foo`218// CHECK: note: try using `attr-dict-with-keyword` instead219def DirectiveRegionsInvalidD : TestFormat_Op<[{220 attr-dict $foo221}]> {222 let regions = (region AnyRegion:$foo);223}224 225//===----------------------------------------------------------------------===//226// results227//===----------------------------------------------------------------------===//228 229// CHECK: error: 'results' directive can can only be used as a child to a 'type' directive230def DirectiveResultsInvalidA : TestFormat_Op<[{231 results232}]>;233 234//===----------------------------------------------------------------------===//235// successors236//===----------------------------------------------------------------------===//237 238// CHECK: error: 'successors' is only valid as a top-level directive239def DirectiveSuccessorsInvalidA : TestFormat_Op<[{240 type(successors)241}]>;242 243//===----------------------------------------------------------------------===//244// type245//===----------------------------------------------------------------------===//246 247// CHECK: error: expected '(' before argument list248def DirectiveTypeInvalidA : TestFormat_Op<[{249 type250}]>;251// CHECK: error: expected literal, variable, directive, or optional group252def DirectiveTypeInvalidB : TestFormat_Op<[{253 type(254}]>;255// CHECK: error: expected ')' after argument list256def DirectiveTypeInvalidC : TestFormat_Op<[{257 type(operands258}]>;259 260//===----------------------------------------------------------------------===//261// functional-type/type operands262//===----------------------------------------------------------------------===//263 264// CHECK: error: literals may only be used in the top-level section of the format265def DirectiveTypeZOperandInvalidA : TestFormat_Op<[{266 type(`literal`)267}]>;268// CHECK: error: 'operands' 'type' is already bound269def DirectiveTypeZOperandInvalidB : TestFormat_Op<[{270 type(operands) type(operands)271}]>;272// CHECK: error: 'operands' 'type' is already bound273def DirectiveTypeZOperandInvalidC : TestFormat_Op<[{274 type($operand) type(operands)275}]>, Arguments<(ins I64:$operand)>;276// CHECK: error: 'type' of 'operand' is already bound277def DirectiveTypeZOperandInvalidD : TestFormat_Op<[{278 type(operands) type($operand)279}]>, Arguments<(ins I64:$operand)>;280// CHECK: error: 'type' of 'operand' is already bound281def DirectiveTypeZOperandInvalidE : TestFormat_Op<[{282 type($operand) type($operand)283}]>, Arguments<(ins I64:$operand)>;284// CHECK: error: 'results' 'type' is already bound285def DirectiveTypeZOperandInvalidF : TestFormat_Op<[{286 type(results) type(results)287}]>;288// CHECK: error: 'results' 'type' is already bound289def DirectiveTypeZOperandInvalidG : TestFormat_Op<[{290 type($result) type(results)291}]>, Results<(outs I64:$result)>;292// CHECK: error: 'type' of 'result' is already bound293def DirectiveTypeZOperandInvalidH : TestFormat_Op<[{294 type(results) type($result)295}]>, Results<(outs I64:$result)>;296// CHECK: error: 'type' of 'result' is already bound297def DirectiveTypeZOperandInvalidI : TestFormat_Op<[{298 type($result) type($result)299}]>, Results<(outs I64:$result)>;300 301//===----------------------------------------------------------------------===//302// Literals303//===----------------------------------------------------------------------===//304 305// Test all of the valid literals.306// CHECK: error: expected valid literal but got 'a:': keywords should contain only alphanum, '_', '$', or '.' characters307def LiteralInvalidA : TestFormat_Op<[{308 `a:`309}]>;310// CHECK: error: expected valid literal but got '1': single character literal must be a letter or one of '_:,=<>()[]{}?+-*'311def LiteralInvalidB : TestFormat_Op<[{312 `1`313}]>;314// CHECK: error: expected valid literal but got ':abc': valid keyword starts with a letter or '_'315def LiteralInvalidC : TestFormat_Op<[{316 `:abc`317}]>;318 319// CHECK: error: unexpected end of file in literal320// CHECK: error: expected literal, variable, directive, or optional group321def LiteralInvalidD : TestFormat_Op<[{322 `323}]>;324 325//===----------------------------------------------------------------------===//326// OIList Element327//===----------------------------------------------------------------------===//328 329// CHECK: error: format ambiguity because bar is used in two adjacent oilist elements.330def OIListAdjacentOIList : TestFormat_Op<[{331 oilist ( `foo` | `bar` ) oilist ( `bar` | `buzz` ) attr-dict332}]>;333// CHECK: error: expected literal, but got ')'334def OIListErrorExpectedLiteral : TestFormat_Op<[{335 oilist( `keyword` | ) attr-dict336}]>;337// CHECK: error: expected literal, but got ')'338def OIListErrorExpectedEmpty : TestFormat_Op<[{339 oilist() attr-dict340}]>;341// CHECK: error: expected literal, but got '$arg0'342def OIListErrorNoLiteral : TestFormat_Op<[{343 oilist( $arg0 `:` type($arg0) | $arg1 `:` type($arg1) ) attr-dict344}], [AttrSizedOperandSegments]>, Arguments<(ins Optional<AnyType>:$arg0, Optional<AnyType>:$arg1)>;345// CHECK: error: format ambiguity because foo is used both in oilist element and the adjacent literal.346def OIListLiteralAmbiguity : TestFormat_Op<[{347 oilist( `foo` | `bar` ) `foo` attr-dict348}]>;349// CHECK: error: expected '(' before oilist argument list350def OIListStartingToken : TestFormat_Op<[{351 oilist `wrong` attr-dict352}]>;353 354//===----------------------------------------------------------------------===//355// Optional Groups356//===----------------------------------------------------------------------===//357 358// CHECK: error: optional groups can only be used as top-level elements359def OptionalInvalidA : TestFormat_Op<[{360 type(($attr^)?) attr-dict361}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;362// CHECK: error: expected literal, variable, directive, or optional group363def OptionalInvalidB : TestFormat_Op<[{364 () attr-dict365}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;366// CHECK: error: optional group has no anchor element367def OptionalInvalidC : TestFormat_Op<[{368 ($attr)? attr-dict369}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;370// CHECK: error: first parsable element of an optional group must be a literal, variable, or custom directive371def OptionalInvalidD : TestFormat_Op<[{372 (type($operand) $operand^)? attr-dict373}]>, Arguments<(ins Optional<I64>:$operand)>;374// CHECK: error: only literals, types, and variables can be used within an optional group375def OptionalInvalidE : TestFormat_Op<[{376 (`,` $attr^ type(operands))? attr-dict377}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;378// CHECK: error: only one element can be marked as the anchor of an optional group379def OptionalInvalidF : TestFormat_Op<[{380 ($attr^ $attr2^)? attr-dict381}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr, OptionalAttr<I64Attr>:$attr2)>;382// CHECK: error: only optional or default-valued attributes can be used to anchor an optional group383def OptionalInvalidG : TestFormat_Op<[{384 ($attr^)? attr-dict385}]>, Arguments<(ins I64Attr:$attr)>;386// CHECK: error: only variable length operands can be used within an optional group387def OptionalInvalidH : TestFormat_Op<[{388 ($arg^)? attr-dict389}]>, Arguments<(ins I64:$arg)>;390// CHECK: error: only literals, types, and variables can be used within an optional group391def OptionalInvalidI : TestFormat_Op<[{392 (functional-type($arg, results)^)? attr-dict393}]>, Arguments<(ins Variadic<I64>:$arg)>;394// CHECK: error: only literals, types, and variables can be used within an optional group395def OptionalInvalidJ : TestFormat_Op<[{396 (attr-dict^)?397}]>;398// CHECK: error: expected '?' after optional group399def OptionalInvalidK : TestFormat_Op<[{400 ($arg^)401}]>, Arguments<(ins Variadic<I64>:$arg)>;402// CHECK: error: only variable length operands can be used within an optional group403def OptionalInvalidL : TestFormat_Op<[{404 (custom<MyDirective>($arg)^)?405}]>, Arguments<(ins I64:$arg)>;406// CHECK: error: only variables and types can be used to anchor an optional group407def OptionalInvalidM : TestFormat_Op<[{408 (` `^)?409}]>, Arguments<(ins)>;410// CHECK: error: expected '(' to start else branch of optional group411def OptionalInvalidN : TestFormat_Op<[{412 ($arg^):413}]>, Arguments<(ins Variadic<I64>:$arg)>;414// CHECK: error: expected literal, variable, directive, or optional group415def OptionalInvalidO : TestFormat_Op<[{416 ($arg^):(`test`417}]>, Arguments<(ins Variadic<I64>:$arg)>;418// CHECK: error: expected '?' after optional group419def OptionalInvalidP : TestFormat_Op<[{420 ($arg^):(`test`)421}]>, Arguments<(ins Variadic<I64>:$arg)>;422 423//===----------------------------------------------------------------------===//424// Strings425//===----------------------------------------------------------------------===//426 427// CHECK: error: strings may only be used as 'custom' directive arguments428def StringInvalidA : TestFormat_Op<[{ "foo" }]>;429 430//===----------------------------------------------------------------------===//431// Variables432//===----------------------------------------------------------------------===//433 434// CHECK: error: expected variable to refer to an argument, region, result, or successor435def VariableInvalidA : TestFormat_Op<[{436 $unknown_arg attr-dict437}]>;438// CHECK: error: attribute 'attr' is already bound439def VariableInvalidB : TestFormat_Op<[{440 $attr $attr attr-dict441}]>, Arguments<(ins I64Attr:$attr)>;442// CHECK: error: operand 'operand' is already bound443def VariableInvalidC : TestFormat_Op<[{444 $operand $operand attr-dict445}]>, Arguments<(ins I64:$operand)>;446// CHECK: error: operand 'operand' is already bound447def VariableInvalidD : TestFormat_Op<[{448 operands $operand attr-dict449}]>, Arguments<(ins I64:$operand)>;450// CHECK: error: result variables can can only be used as a child to a 'type' directive451def VariableInvalidE : TestFormat_Op<[{452 $result attr-dict453}]>, Results<(outs I64:$result)>;454// CHECK: error: successor 'successor' is already bound455def VariableInvalidF : TestFormat_Op<[{456 $successor $successor attr-dict457}]> {458 let successors = (successor AnySuccessor:$successor);459}460// CHECK: error: successor 'successor' is already bound461def VariableInvalidG : TestFormat_Op<[{462 successors $successor attr-dict463}]> {464 let successors = (successor AnySuccessor:$successor);465}466// CHECK: error: region 'region' is already bound467def VariableInvalidK : TestFormat_Op<[{468 $region $region attr-dict469}]> {470 let regions = (region AnyRegion:$region);471}472// CHECK: error: region 'region' is already bound473def VariableInvalidL : TestFormat_Op<[{474 regions $region attr-dict475}]> {476 let regions = (region AnyRegion:$region);477}478// CHECK: error: regions can only be used at the top level479def VariableInvalidM : TestFormat_Op<[{480 type($region)481}]> {482 let regions = (region AnyRegion:$region);483}484// CHECK: error: region #0, named 'region', not found485def VariableInvalidN : TestFormat_Op<[{486 attr-dict487}]> {488 let regions = (region AnyRegion:$region);489}490 491// CHECK: error: property 'prop' is already bound492def VariableInvalidO : TestFormat_Op<[{493 custom<Test>($prop, $prop) attr-dict494}]>, Arguments<(ins IntProp<"int64_t">:$prop)>;495 496// CHECK: error: property 'prop' must be bound before it is referenced497def VariableInvalidP : TestFormat_Op<[{498 custom<Test>(ref($prop)) attr-dict499}]>, Arguments<(ins IntProp<"int64_t">:$prop)>;500 501//===----------------------------------------------------------------------===//502// Coverage Checks503//===----------------------------------------------------------------------===//504 505// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred506// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format507def ZCoverageInvalidA : TestFormat_Op<[{508 attr-dict509}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;510// CHECK: error: operand #0, named 'operand', not found511// CHECK: note: suggest adding a '$operand' directive to the custom assembly format512def ZCoverageInvalidB : TestFormat_Op<[{513 type($result) attr-dict514}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;515// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred516// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format517def ZCoverageInvalidC : TestFormat_Op<[{518 $operand type($result) attr-dict519}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;520// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred521// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format522def ZCoverageInvalidD : TestFormat_Op<[{523 operands attr-dict524}]>, Arguments<(ins Variadic<I64>:$operand)>;525// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred526// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format527def ZCoverageInvalidE : TestFormat_Op<[{528 attr-dict529}]>, Results<(outs Variadic<I64>:$result)>;530// CHECK: error: successor #0, named 'successor', not found531// CHECK: note: suggest adding a '$successor' directive to the custom assembly format532def ZCoverageInvalidF : TestFormat_Op<[{533 attr-dict534}]> {535 let successors = (successor AnySuccessor:$successor);536}537// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred538// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format539def ZCoverageInvalidG : TestFormat_Op<[{540 operands attr-dict541}]>, Arguments<(ins Optional<I64>:$operand)>;542// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred543// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format544def ZCoverageInvalidH : TestFormat_Op<[{545 attr-dict546}]>, Results<(outs Optional<I64>:$result)>;547