1// RUN: mlir-tblgen -gen-op-decls -asmformat-error-is-fatal=false -I %S/../../include %s -o=%t 2>&1 | FileCheck %s 2 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// Directives 18//===----------------------------------------------------------------------===// 19 20//===----------------------------------------------------------------------===// 21// attr-dict 22 23// CHECK: error: 'attr-dict' directive not found 24def DirectiveAttrDictInvalidA : TestFormat_Op<[{ 25}]>; 26// CHECK: error: 'attr-dict' directive has already been seen 27def DirectiveAttrDictInvalidB : TestFormat_Op<[{ 28 attr-dict attr-dict 29}]>; 30// CHECK: error: 'attr-dict' directive has already been seen 31def DirectiveAttrDictInvalidC : TestFormat_Op<[{ 32 attr-dict attr-dict-with-keyword 33}]>; 34// CHECK: error: 'attr-dict' directive can only be used as a top-level directive 35def DirectiveAttrDictInvalidD : TestFormat_Op<[{ 36 type(attr-dict) 37}]>; 38 39//===----------------------------------------------------------------------===// 40// custom 41 42// CHECK: error: expected '<' before custom directive name 43def DirectiveCustomInvalidA : TestFormat_Op<[{ 44 custom( 45}]>; 46// CHECK: error: expected custom directive name identifier 47def DirectiveCustomInvalidB : TestFormat_Op<[{ 48 custom<> 49}]>; 50// CHECK: error: expected '>' after custom directive name 51def DirectiveCustomInvalidC : TestFormat_Op<[{ 52 custom<MyDirective( 53}]>; 54// CHECK: error: expected '(' before custom directive parameters 55def DirectiveCustomInvalidD : TestFormat_Op<[{ 56 custom<MyDirective>) 57}]>; 58// CHECK: error: only variables and types may be used as parameters to a custom directive 59def DirectiveCustomInvalidE : TestFormat_Op<[{ 60 custom<MyDirective>(operands) 61}]>; 62// CHECK: error: expected ')' after custom directive parameters 63def DirectiveCustomInvalidF : TestFormat_Op<[{ 64 custom<MyDirective>($operand< 65}]>, Arguments<(ins I64:$operand)>; 66// CHECK: error: type directives within a custom directive may only refer to variables 67def DirectiveCustomInvalidH : TestFormat_Op<[{ 68 custom<MyDirective>(type(operands)) 69}]>; 70 71//===----------------------------------------------------------------------===// 72// functional-type 73 74// CHECK: error: 'functional-type' is only valid as a top-level directive 75def DirectiveFunctionalTypeInvalidA : TestFormat_Op<[{ 76 functional-type(functional-type) 77}]>; 78// CHECK: error: expected '(' before argument list 79def DirectiveFunctionalTypeInvalidB : TestFormat_Op<[{ 80 functional-type 81}]>; 82// CHECK: error: expected literal, variable, directive, or optional group 83def DirectiveFunctionalTypeInvalidC : TestFormat_Op<[{ 84 functional-type( 85}]>; 86// CHECK: error: expected ',' after inputs argument 87def DirectiveFunctionalTypeInvalidD : TestFormat_Op<[{ 88 functional-type(operands 89}]>; 90// CHECK: error: expected literal, variable, directive, or optional group 91def DirectiveFunctionalTypeInvalidE : TestFormat_Op<[{ 92 functional-type(operands, 93}]>; 94// CHECK: error: expected ')' after argument list 95def DirectiveFunctionalTypeInvalidF : TestFormat_Op<[{ 96 functional-type(operands, results 97}]>; 98 99//===----------------------------------------------------------------------===// 100// operands 101 102// CHECK: error: 'operands' directive creates overlap in format 103def DirectiveOperandsInvalidA : TestFormat_Op<[{ 104 operands operands 105}]>; 106// CHECK: error: 'operands' directive creates overlap in format 107def DirectiveOperandsInvalidB : TestFormat_Op<[{ 108 $operand operands 109}]>, Arguments<(ins I64:$operand)>; 110 111//===----------------------------------------------------------------------===// 112// ref 113 114// CHECK: error: 'ref' is only valid within a `custom` directive 115def DirectiveRefInvalidA : TestFormat_Op<[{ 116 ref(type($operand)) 117}]>, Arguments<(ins I64:$operand)>; 118 119// CHECK: error: 'ref' of 'type($operand)' is not bound by a prior 'type' directive 120def DirectiveRefInvalidB : TestFormat_Op<[{ 121 custom<Foo>(ref(type($operand))) 122}]>, Arguments<(ins I64:$operand)>; 123 124// CHECK: error: 'ref' of 'type(operands)' is not bound by a prior 'type' directive 125def DirectiveRefInvalidC : TestFormat_Op<[{ 126 custom<Foo>(ref(type(operands))) 127}]>; 128 129// CHECK: error: 'ref' of 'type($result)' is not bound by a prior 'type' directive 130def DirectiveRefInvalidD : TestFormat_Op<[{ 131 custom<Foo>(ref(type($result))) 132}]>, Results<(outs I64:$result)>; 133 134// CHECK: error: 'ref' of 'type(results)' is not bound by a prior 'type' directive 135def DirectiveRefInvalidE : TestFormat_Op<[{ 136 custom<Foo>(ref(type(results))) 137}]>; 138 139// CHECK: error: 'ref' of 'successors' is not bound by a prior 'successors' directive 140def DirectiveRefInvalidF : TestFormat_Op<[{ 141 custom<Foo>(ref(successors)) 142}]>; 143 144// CHECK: error: 'ref' of 'regions' is not bound by a prior 'regions' directive 145def DirectiveRefInvalidG : TestFormat_Op<[{ 146 custom<Foo>(ref(regions)) 147}]>; 148 149// CHECK: error: expected '(' before argument list 150def DirectiveRefInvalidH : TestFormat_Op<[{ 151 custom<Foo>(ref) 152}]>; 153 154// CHECK: error: expected ')' after argument list 155def DirectiveRefInvalidI : TestFormat_Op<[{ 156 operands custom<Foo>(ref(operands( 157}]>; 158 159// CHECK: error: 'ref' of 'operands' is not bound by a prior 'operands' directive 160def DirectiveRefInvalidJ : TestFormat_Op<[{ 161 custom<Foo>(ref(operands)) 162}]>; 163 164// CHECK: error: 'ref' of 'attr-dict' is not bound by a prior 'attr-dict' directive 165def DirectiveRefInvalidK : TestFormat_Op<[{ 166 custom<Foo>(ref(attr-dict)) 167}]>; 168 169// CHECK: error: successor 'successor' must be bound before it is referenced 170def DirectiveRefInvalidL : TestFormat_Op<[{ 171 custom<Foo>(ref($successor)) 172}]> { 173 let successors = (successor AnySuccessor:$successor); 174} 175 176// CHECK: error: region 'region' must be bound before it is referenced 177def DirectiveRefInvalidM : TestFormat_Op<[{ 178 custom<Foo>(ref($region)) 179}]> { 180 let regions = (region AnyRegion:$region); 181} 182 183// CHECK: error: attribute 'attr' must be bound before it is referenced 184def DirectiveRefInvalidN : TestFormat_Op<[{ 185 custom<Foo>(ref($attr)) 186}]>, Arguments<(ins I64Attr:$attr)>; 187 188 189// CHECK: error: operand 'operand' must be bound before it is referenced 190def DirectiveRefInvalidO : TestFormat_Op<[{ 191 custom<Foo>(ref($operand)) 192}]>, Arguments<(ins I64:$operand)>; 193 194//===----------------------------------------------------------------------===// 195// regions 196 197// CHECK: error: 'regions' directive creates overlap in format 198def DirectiveRegionsInvalidA : TestFormat_Op<[{ 199 regions regions attr-dict 200}]>; 201// CHECK: error: 'regions' directive creates overlap in format 202def DirectiveRegionsInvalidB : TestFormat_Op<[{ 203 $region regions attr-dict 204}]> { 205 let regions = (region AnyRegion:$region); 206} 207// CHECK: error: 'regions' is only valid as a top-level directive 208def DirectiveRegionsInvalidC : TestFormat_Op<[{ 209 type(regions) 210}]>; 211// CHECK: error: format ambiguity caused by `attr-dict` directive followed by region `foo` 212// CHECK: note: try using `attr-dict-with-keyword` instead 213def DirectiveRegionsInvalidD : TestFormat_Op<[{ 214 attr-dict $foo 215}]> { 216 let regions = (region AnyRegion:$foo); 217} 218 219//===----------------------------------------------------------------------===// 220// results 221 222// CHECK: error: 'results' directive can can only be used as a child to a 'type' directive 223def DirectiveResultsInvalidA : TestFormat_Op<[{ 224 results 225}]>; 226 227//===----------------------------------------------------------------------===// 228// successors 229 230// CHECK: error: 'successors' is only valid as a top-level directive 231def DirectiveSuccessorsInvalidA : TestFormat_Op<[{ 232 type(successors) 233}]>; 234 235//===----------------------------------------------------------------------===// 236// type 237 238// CHECK: error: expected '(' before argument list 239def DirectiveTypeInvalidA : TestFormat_Op<[{ 240 type 241}]>; 242// CHECK: error: expected literal, variable, directive, or optional group 243def DirectiveTypeInvalidB : TestFormat_Op<[{ 244 type( 245}]>; 246// CHECK: error: expected ')' after argument list 247def DirectiveTypeInvalidC : TestFormat_Op<[{ 248 type(operands 249}]>; 250 251//===----------------------------------------------------------------------===// 252// functional-type/type operands 253 254// CHECK: error: literals may only be used in the top-level section of the format 255def DirectiveTypeZOperandInvalidA : TestFormat_Op<[{ 256 type(`literal`) 257}]>; 258// CHECK: error: 'operands' 'type' is already bound 259def DirectiveTypeZOperandInvalidB : TestFormat_Op<[{ 260 type(operands) type(operands) 261}]>; 262// CHECK: error: 'operands' 'type' is already bound 263def DirectiveTypeZOperandInvalidC : TestFormat_Op<[{ 264 type($operand) type(operands) 265}]>, Arguments<(ins I64:$operand)>; 266// CHECK: error: 'type' of 'operand' is already bound 267def DirectiveTypeZOperandInvalidD : TestFormat_Op<[{ 268 type(operands) type($operand) 269}]>, Arguments<(ins I64:$operand)>; 270// CHECK: error: 'type' of 'operand' is already bound 271def DirectiveTypeZOperandInvalidE : TestFormat_Op<[{ 272 type($operand) type($operand) 273}]>, Arguments<(ins I64:$operand)>; 274// CHECK: error: 'results' 'type' is already bound 275def DirectiveTypeZOperandInvalidF : TestFormat_Op<[{ 276 type(results) type(results) 277}]>; 278// CHECK: error: 'results' 'type' is already bound 279def DirectiveTypeZOperandInvalidG : TestFormat_Op<[{ 280 type($result) type(results) 281}]>, Results<(outs I64:$result)>; 282// CHECK: error: 'type' of 'result' is already bound 283def DirectiveTypeZOperandInvalidH : TestFormat_Op<[{ 284 type(results) type($result) 285}]>, Results<(outs I64:$result)>; 286// CHECK: error: 'type' of 'result' is already bound 287def DirectiveTypeZOperandInvalidI : TestFormat_Op<[{ 288 type($result) type($result) 289}]>, Results<(outs I64:$result)>; 290 291//===----------------------------------------------------------------------===// 292// Literals 293//===----------------------------------------------------------------------===// 294 295// Test all of the valid literals. 296// CHECK: error: expected valid literal but got 'a:': keywords should contain only alphanum, '_', '$', or '.' characters 297def LiteralInvalidA : TestFormat_Op<[{ 298 `a:` 299}]>; 300// CHECK: error: expected valid literal but got '1': single character literal must be a letter or one of '_:,=<>()[]{}?+*' 301def LiteralInvalidB : TestFormat_Op<[{ 302 `1` 303}]>; 304// CHECK: error: expected valid literal but got ':abc': valid keyword starts with a letter or '_' 305def LiteralInvalidC : TestFormat_Op<[{ 306 `:abc` 307}]>; 308 309// CHECK: error: unexpected end of file in literal 310// CHECK: error: expected literal, variable, directive, or optional group 311def LiteralInvalidD : TestFormat_Op<[{ 312 ` 313}]>; 314 315//===----------------------------------------------------------------------===// 316// OIList Element 317//===----------------------------------------------------------------------===// 318 319// CHECK: error: format ambiguity because bar is used in two adjacent oilist elements. 320def OIListAdjacentOIList : TestFormat_Op<[{ 321 oilist ( `foo` | `bar` ) oilist ( `bar` | `buzz` ) attr-dict 322}]>; 323// CHECK: error: expected literal, but got ')' 324def OIListErrorExpectedLiteral : TestFormat_Op<[{ 325 oilist( `keyword` | ) attr-dict 326}]>; 327// CHECK: error: expected literal, but got ')' 328def OIListErrorExpectedEmpty : TestFormat_Op<[{ 329 oilist() attr-dict 330}]>; 331// CHECK: error: expected literal, but got '$arg0' 332def OIListErrorNoLiteral : TestFormat_Op<[{ 333 oilist( $arg0 `:` type($arg0) | $arg1 `:` type($arg1) ) attr-dict 334}], [AttrSizedOperandSegments]>, Arguments<(ins Optional<AnyType>:$arg0, Optional<AnyType>:$arg1)>; 335// CHECK: error: format ambiguity because foo is used both in oilist element and the adjacent literal. 336def OIListLiteralAmbiguity : TestFormat_Op<[{ 337 oilist( `foo` | `bar` ) `foo` attr-dict 338}]>; 339// CHECK: error: expected '(' before oilist argument list 340def OIListStartingToken : TestFormat_Op<[{ 341 oilist `wrong` attr-dict 342}]>; 343 344//===----------------------------------------------------------------------===// 345// Optional Groups 346//===----------------------------------------------------------------------===// 347 348// CHECK: error: optional groups can only be used as top-level elements 349def OptionalInvalidA : TestFormat_Op<[{ 350 type(($attr^)?) attr-dict 351}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>; 352// CHECK: error: expected literal, variable, directive, or optional group 353def OptionalInvalidB : TestFormat_Op<[{ 354 () attr-dict 355}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>; 356// CHECK: error: optional group has no anchor element 357def OptionalInvalidC : TestFormat_Op<[{ 358 ($attr)? attr-dict 359}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>; 360// CHECK: error: first parsable element of an optional group must be a literal, variable, or custom directive 361def OptionalInvalidD : TestFormat_Op<[{ 362 (type($operand) $operand^)? attr-dict 363}]>, Arguments<(ins Optional<I64>:$operand)>; 364// CHECK: error: only literals, types, and variables can be used within an optional group 365def OptionalInvalidE : TestFormat_Op<[{ 366 (`,` $attr^ type(operands))? attr-dict 367}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>; 368// CHECK: error: only one element can be marked as the anchor of an optional group 369def OptionalInvalidF : TestFormat_Op<[{ 370 ($attr^ $attr2^)? attr-dict 371}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr, OptionalAttr<I64Attr>:$attr2)>; 372// CHECK: error: only optional or default-valued attributes can be used to anchor an optional group 373def OptionalInvalidG : TestFormat_Op<[{ 374 ($attr^)? attr-dict 375}]>, Arguments<(ins I64Attr:$attr)>; 376// CHECK: error: only variable length operands can be used within an optional group 377def OptionalInvalidH : TestFormat_Op<[{ 378 ($arg^)? attr-dict 379}]>, Arguments<(ins I64:$arg)>; 380// CHECK: error: only literals, types, and variables can be used within an optional group 381def OptionalInvalidI : TestFormat_Op<[{ 382 (functional-type($arg, results)^)? attr-dict 383}]>, Arguments<(ins Variadic<I64>:$arg)>; 384// CHECK: error: only literals, types, and variables can be used within an optional group 385def OptionalInvalidJ : TestFormat_Op<[{ 386 (attr-dict^)? 387}]>; 388// CHECK: error: expected '?' after optional group 389def OptionalInvalidK : TestFormat_Op<[{ 390 ($arg^) 391}]>, Arguments<(ins Variadic<I64>:$arg)>; 392// CHECK: error: only variable length operands can be used within an optional group 393def OptionalInvalidL : TestFormat_Op<[{ 394 (custom<MyDirective>($arg)^)? 395}]>, Arguments<(ins I64:$arg)>; 396// CHECK: error: only variables and types can be used to anchor an optional group 397def OptionalInvalidM : TestFormat_Op<[{ 398 (` `^)? 399}]>, Arguments<(ins)>; 400// CHECK: error: expected '(' to start else branch of optional group 401def OptionalInvalidN : TestFormat_Op<[{ 402 ($arg^): 403}]>, Arguments<(ins Variadic<I64>:$arg)>; 404// CHECK: error: expected literal, variable, directive, or optional group 405def OptionalInvalidO : TestFormat_Op<[{ 406 ($arg^):(`test` 407}]>, Arguments<(ins Variadic<I64>:$arg)>; 408// CHECK: error: expected '?' after optional group 409def OptionalInvalidP : TestFormat_Op<[{ 410 ($arg^):(`test`) 411}]>, Arguments<(ins Variadic<I64>:$arg)>; 412 413//===----------------------------------------------------------------------===// 414// Strings 415//===----------------------------------------------------------------------===// 416 417// CHECK: error: strings may only be used as 'custom' directive arguments 418def StringInvalidA : TestFormat_Op<[{ "foo" }]>; 419 420//===----------------------------------------------------------------------===// 421// Variables 422//===----------------------------------------------------------------------===// 423 424// CHECK: error: expected variable to refer to an argument, region, result, or successor 425def VariableInvalidA : TestFormat_Op<[{ 426 $unknown_arg attr-dict 427}]>; 428// CHECK: error: attribute 'attr' is already bound 429def VariableInvalidB : TestFormat_Op<[{ 430 $attr $attr attr-dict 431}]>, Arguments<(ins I64Attr:$attr)>; 432// CHECK: error: operand 'operand' is already bound 433def VariableInvalidC : TestFormat_Op<[{ 434 $operand $operand attr-dict 435}]>, Arguments<(ins I64:$operand)>; 436// CHECK: error: operand 'operand' is already bound 437def VariableInvalidD : TestFormat_Op<[{ 438 operands $operand attr-dict 439}]>, Arguments<(ins I64:$operand)>; 440// CHECK: error: result variables can can only be used as a child to a 'type' directive 441def VariableInvalidE : TestFormat_Op<[{ 442 $result attr-dict 443}]>, Results<(outs I64:$result)>; 444// CHECK: error: successor 'successor' is already bound 445def VariableInvalidF : TestFormat_Op<[{ 446 $successor $successor attr-dict 447}]> { 448 let successors = (successor AnySuccessor:$successor); 449} 450// CHECK: error: successor 'successor' is already bound 451def VariableInvalidG : TestFormat_Op<[{ 452 successors $successor attr-dict 453}]> { 454 let successors = (successor AnySuccessor:$successor); 455} 456// CHECK: error: region 'region' is already bound 457def VariableInvalidK : TestFormat_Op<[{ 458 $region $region attr-dict 459}]> { 460 let regions = (region AnyRegion:$region); 461} 462// CHECK: error: region 'region' is already bound 463def VariableInvalidL : TestFormat_Op<[{ 464 regions $region attr-dict 465}]> { 466 let regions = (region AnyRegion:$region); 467} 468// CHECK: error: regions can only be used at the top level 469def VariableInvalidM : TestFormat_Op<[{ 470 type($region) 471}]> { 472 let regions = (region AnyRegion:$region); 473} 474// CHECK: error: region #0, named 'region', not found 475def VariableInvalidN : TestFormat_Op<[{ 476 attr-dict 477}]> { 478 let regions = (region AnyRegion:$region); 479} 480 481// CHECK: error: property 'prop' is already bound 482def VariableInvalidO : TestFormat_Op<[{ 483 custom<Test>($prop, $prop) attr-dict 484}]>, Arguments<(ins IntProp<"int64_t">:$prop)>; 485 486// CHECK: error: property 'prop' must be bound before it is referenced 487def VariableInvalidP : TestFormat_Op<[{ 488 custom<Test>(ref($prop)) attr-dict 489}]>, Arguments<(ins IntProp<"int64_t">:$prop)>; 490 491//===----------------------------------------------------------------------===// 492// Coverage Checks 493//===----------------------------------------------------------------------===// 494 495// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred 496// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format 497def ZCoverageInvalidA : TestFormat_Op<[{ 498 attr-dict 499}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>; 500// CHECK: error: operand #0, named 'operand', not found 501// CHECK: note: suggest adding a '$operand' directive to the custom assembly format 502def ZCoverageInvalidB : TestFormat_Op<[{ 503 type($result) attr-dict 504}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>; 505// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred 506// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format 507def ZCoverageInvalidC : TestFormat_Op<[{ 508 $operand type($result) attr-dict 509}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>; 510// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred 511// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format 512def ZCoverageInvalidD : TestFormat_Op<[{ 513 operands attr-dict 514}]>, Arguments<(ins Variadic<I64>:$operand)>; 515// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred 516// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format 517def ZCoverageInvalidE : TestFormat_Op<[{ 518 attr-dict 519}]>, Results<(outs Variadic<I64>:$result)>; 520// CHECK: error: successor #0, named 'successor', not found 521// CHECK: note: suggest adding a '$successor' directive to the custom assembly format 522def ZCoverageInvalidF : TestFormat_Op<[{ 523 attr-dict 524}]> { 525 let successors = (successor AnySuccessor:$successor); 526} 527// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred 528// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format 529def ZCoverageInvalidG : TestFormat_Op<[{ 530 operands attr-dict 531}]>, Arguments<(ins Optional<I64>:$operand)>; 532// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred 533// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format 534def ZCoverageInvalidH : TestFormat_Op<[{ 535 attr-dict 536}]>, Results<(outs Optional<I64>:$result)>; 537