xref: /llvm-project/mlir/test/lib/Dialect/Test/TestOpsSyntax.td (revision 378e1793379c9c63a4265ecf55c47308410ed25d)
1
2//===-- TestOpsSyntax.td - Operations for testing syntax ---*- tablegen -*-===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef TEST_OPS_SYNTAX
11#define TEST_OPS_SYNTAX
12
13include "TestAttrDefs.td"
14include "TestDialect.td"
15include "TestTypeDefs.td"
16include "mlir/Interfaces/InferTypeOpInterface.td"
17include "mlir/IR/OpBase.td"
18
19class TEST_Op<string mnemonic, list<Trait> traits = []> :
20    Op<Test_Dialect, mnemonic, traits>;
21
22def WrappingRegionOp : TEST_Op<"wrapping_region",
23    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
24  let summary =  "wrapping region operation";
25  let description = [{
26    Test op wrapping another op in a region, to test calling
27    parseGenericOperation from the custom parser.
28  }];
29
30  let results = (outs Variadic<AnyType>);
31  let regions = (region SizedRegion<1>:$region);
32  let hasCustomAssemblyFormat = 1;
33}
34
35def PrettyPrintedRegionOp : TEST_Op<"pretty_printed_region",
36    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
37  let summary =  "pretty_printed_region operation";
38  let description = [{
39    Test-op can be printed either in a "pretty" or "non-pretty" way based on
40    some criteria. The custom parser parsers both the versions while testing
41    APIs: parseCustomOperationName & parseGenericOperationAfterOpName.
42  }];
43  let arguments = (ins
44    AnyType:$input1,
45    AnyType:$input2
46  );
47
48  let results = (outs AnyType);
49  let regions = (region SizedRegion<1>:$region);
50  let hasCustomAssemblyFormat = 1;
51}
52
53def PolyForOp : TEST_Op<"polyfor", [OpAsmOpInterface]> {
54  let summary =  "polyfor operation";
55  let description = [{
56    Test op with multiple region arguments, each argument of index type.
57  }];
58  let extraClassDeclaration = [{
59    void getAsmBlockArgumentNames(mlir::Region &region,
60                                  mlir::OpAsmSetValueNameFn setNameFn);
61  }];
62  let regions = (region SizedRegion<1>:$region);
63  let hasCustomAssemblyFormat = 1;
64}
65
66def TestAttrWithLoc : TEST_Op<"attr_with_loc"> {
67  let summary = "op's attribute has a location";
68  let arguments = (ins AnyAttr:$loc, AnyAttr:$value);
69  let assemblyFormat = "`(` $value `` custom<OptionalLoc>($loc) `)` attr-dict";
70}
71
72// -----
73
74// This is used to test that the fallback for a custom op's parser and printer
75// is the dialect parser and printer hooks.
76def CustomFormatFallbackOp : TEST_Op<"dialect_custom_format_fallback">;
77
78// Ops related to OIList primitive
79def OIListTrivial : TEST_Op<"oilist_with_keywords_only"> {
80  let arguments = (ins UnitAttr:$keyword, UnitAttr:$otherKeyword,
81                       UnitAttr:$diffNameUnitAttrKeyword);
82  let assemblyFormat = [{
83    oilist( `keyword` $keyword
84          | `otherKeyword` $otherKeyword
85          | `thirdKeyword` $diffNameUnitAttrKeyword) attr-dict
86  }];
87}
88
89// Ops related to OIList primitive
90def OIListTrivialProperties : TEST_Op<"oilist_with_keywords_only_properties"> {
91  let arguments = (ins UnitProp:$keyword, UnitProp:$otherKeyword,
92                       UnitProp:$diffNameUnitPropKeyword);
93  let assemblyFormat = [{
94    oilist( `keyword` $keyword
95          | `otherKeyword` $otherKeyword
96          | `thirdKeyword` $diffNameUnitPropKeyword) attr-dict
97  }];
98}
99
100def OIListSimple : TEST_Op<"oilist_with_simple_args", [AttrSizedOperandSegments]> {
101  let arguments = (ins Optional<AnyType>:$arg0,
102                       Optional<AnyType>:$arg1,
103                       Optional<AnyType>:$arg2);
104  let assemblyFormat = [{
105    oilist( `keyword` $arg0 `:` type($arg0)
106          | `otherKeyword` $arg1 `:` type($arg1)
107          | `thirdKeyword` $arg2 `:` type($arg2) ) attr-dict
108  }];
109}
110
111def OIListVariadic : TEST_Op<"oilist_variadic_with_parens", [AttrSizedOperandSegments]> {
112  let arguments = (ins Variadic<AnyType>:$arg0,
113                       Variadic<AnyType>:$arg1,
114                       Variadic<AnyType>:$arg2);
115  let assemblyFormat = [{
116    oilist( `keyword` `(` $arg0 `:` type($arg0) `)`
117          | `otherKeyword` `(` $arg1 `:` type($arg1) `)`
118          | `thirdKeyword` `(` $arg2 `:` type($arg2) `)`) attr-dict
119  }];
120}
121
122def OIListCustom : TEST_Op<"oilist_custom", [AttrSizedOperandSegments]> {
123  let arguments = (ins Variadic<AnyType>:$arg0,
124                       Optional<I32>:$optOperand,
125                       UnitAttr:$nowait);
126  let assemblyFormat = [{
127    oilist( `private` `(` $arg0 `:` type($arg0) `)`
128          | `reduction` custom<CustomOptionalOperand>($optOperand)
129          | `nowait` $nowait
130    ) attr-dict
131  }];
132}
133
134def OIListAllowedLiteral : TEST_Op<"oilist_allowed_literal"> {
135  let assemblyFormat = [{
136    oilist( `foo` | `bar` ) `buzz` attr-dict
137  }];
138}
139
140def TestEllipsisOp : TEST_Op<"ellipsis"> {
141  let arguments = (ins Variadic<AnyType>:$operands, UnitAttr:$variadic);
142  let assemblyFormat = [{
143    `(` $operands (`...` $variadic^)? `)` attr-dict `:` type($operands) `...`
144  }];
145}
146
147def ElseAnchorOp : TEST_Op<"else_anchor"> {
148  let arguments = (ins Optional<AnyType>:$a);
149  let assemblyFormat = "`(` (`?`) : (`` $a^ `:` type($a))? `)` attr-dict";
150}
151
152// This is used to test that the default dialect is not elided when printing an
153// op with dots in the name to avoid parsing ambiguity.
154def OpWithDotInNameOp : TEST_Op<"op.with_dot_in_name"> {
155  let assemblyFormat = "attr-dict";
156}
157
158// --------------
159
160//===----------------------------------------------------------------------===//
161// Test Op Asm Format
162//===----------------------------------------------------------------------===//
163
164def FormatLiteralOp : TEST_Op<"format_literal_op"> {
165  let assemblyFormat = [{
166    `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)`
167    `?` `+` `*` `{` `\n` `}` attr-dict
168  }];
169}
170
171// Test that we elide attributes that are within the syntax.
172def FormatAttrOp : TEST_Op<"format_attr_op"> {
173  let arguments = (ins I64Attr:$attr);
174  let assemblyFormat = "$attr attr-dict";
175}
176
177// Test that we elide optional attributes that are within the syntax.
178def FormatOptAttrAOp : TEST_Op<"format_opt_attr_op_a"> {
179  let arguments = (ins OptionalAttr<I64Attr>:$opt_attr);
180  let assemblyFormat = "(`(` $opt_attr^ `)` )? attr-dict";
181}
182def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> {
183  let arguments = (ins OptionalAttr<I64Attr>:$opt_attr);
184  let assemblyFormat = "($opt_attr^)? attr-dict";
185}
186
187// Test that we format symbol name attributes properly.
188def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> {
189  let arguments = (ins SymbolNameAttr:$attr);
190  let assemblyFormat = "$attr attr-dict";
191}
192
193// Test that we format optional symbol name attributes properly.
194def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> {
195  let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr);
196  let assemblyFormat = "($opt_attr^)? attr-dict";
197}
198
199// Test that we format optional symbol reference attributes properly.
200def FormatOptSymbolRefAttrOp : TEST_Op<"format_opt_symbol_ref_attr_op"> {
201  let arguments = (ins OptionalAttr<SymbolRefAttr>:$opt_attr);
202  let assemblyFormat = "($opt_attr^)? attr-dict";
203}
204
205// Test that we elide attributes that are within the syntax.
206def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> {
207  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr);
208  let assemblyFormat = "attr-dict-with-keyword";
209}
210
211// Test that we don't need to provide types in the format if they are buildable.
212def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> {
213  let arguments = (ins I64:$buildable);
214  let results = (outs I64:$buildable_res);
215  let assemblyFormat = "$buildable attr-dict";
216}
217
218// Test various mixings of region formatting.
219class FormatRegionBase<string suffix, string fmt>
220    : TEST_Op<"format_region_" # suffix # "_op"> {
221  let regions = (region AnyRegion:$region);
222  let assemblyFormat = fmt;
223}
224def FormatRegionAOp : FormatRegionBase<"a", [{
225  regions attr-dict
226}]>;
227def FormatRegionBOp : FormatRegionBase<"b", [{
228  $region attr-dict
229}]>;
230def FormatRegionCOp : FormatRegionBase<"c", [{
231  (`region` $region^)? attr-dict
232}]>;
233class FormatVariadicRegionBase<string suffix, string fmt>
234    : TEST_Op<"format_variadic_region_" # suffix # "_op"> {
235  let regions = (region VariadicRegion<AnyRegion>:$regions);
236  let assemblyFormat = fmt;
237}
238def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{
239  $regions attr-dict
240}]>;
241def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{
242  ($regions^ `found_regions`)? attr-dict
243}]>;
244class FormatRegionImplicitTerminatorBase<string suffix, string fmt>
245    : TEST_Op<"format_implicit_terminator_region_" # suffix # "_op",
246              [SingleBlockImplicitTerminator<"TestReturnOp">]> {
247  let regions = (region AnyRegion:$region);
248  let assemblyFormat = fmt;
249}
250def FormatFormatRegionImplicitTerminatorAOp
251    : FormatRegionImplicitTerminatorBase<"a", [{
252  $region attr-dict
253}]>;
254
255// Test various mixings of result type formatting.
256class FormatResultBase<string suffix, string fmt>
257    : TEST_Op<"format_result_" # suffix # "_op"> {
258  let results = (outs I64:$buildable_res, AnyMemRef:$result);
259  let assemblyFormat = fmt;
260}
261def FormatResultAOp : FormatResultBase<"a", [{
262  type($result) attr-dict
263}]>;
264def FormatResultBOp : FormatResultBase<"b", [{
265  type(results) attr-dict
266}]>;
267def FormatResultCOp : FormatResultBase<"c", [{
268  functional-type($buildable_res, $result) attr-dict
269}]>;
270
271def FormatVariadicResult : TEST_Op<"format_variadic_result"> {
272  let results = (outs Variadic<I64>:$result);
273  let assemblyFormat = [{ `:` type($result) attr-dict}];
274}
275
276def FormatMultipleVariadicResults : TEST_Op<"format_multiple_variadic_results",
277                                            [AttrSizedResultSegments]> {
278  let results = (outs Variadic<I64>:$result0, Variadic<AnyType>:$result1);
279  let assemblyFormat = [{
280    `:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict
281  }];
282}
283
284// Test various mixings of operand type formatting.
285class FormatOperandBase<string suffix, string fmt>
286    : TEST_Op<"format_operand_" # suffix # "_op"> {
287  let arguments = (ins I64:$buildable, AnyMemRef:$operand);
288  let assemblyFormat = fmt;
289}
290
291def FormatOperandAOp : FormatOperandBase<"a", [{
292  operands `:` type(operands) attr-dict
293}]>;
294def FormatOperandBOp : FormatOperandBase<"b", [{
295  operands `:` type($operand) attr-dict
296}]>;
297def FormatOperandCOp : FormatOperandBase<"c", [{
298  $buildable `,` $operand `:` type(operands) attr-dict
299}]>;
300def FormatOperandDOp : FormatOperandBase<"d", [{
301  $buildable `,` $operand `:` type($operand) attr-dict
302}]>;
303def FormatOperandEOp : FormatOperandBase<"e", [{
304  $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict
305}]>;
306
307def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> {
308  let successors = (successor VariadicSuccessor<AnySuccessor>:$targets);
309  let assemblyFormat = "$targets attr-dict";
310}
311
312def FormatVariadicOperand : TEST_Op<"format_variadic_operand"> {
313  let arguments = (ins Variadic<I64>:$operand);
314  let assemblyFormat = [{ $operand `:` type($operand) attr-dict}];
315}
316def FormatVariadicOfVariadicOperand
317   : TEST_Op<"format_variadic_of_variadic_operand"> {
318  let arguments = (ins
319    VariadicOfVariadic<I64, "operand_segments">:$operand,
320    DenseI32ArrayAttr:$operand_segments
321  );
322  let assemblyFormat = [{ $operand `:` type($operand) attr-dict}];
323}
324
325def FormatMultipleVariadicOperands :
326    TEST_Op<"format_multiple_variadic_operands", [AttrSizedOperandSegments]> {
327  let arguments = (ins Variadic<I64>:$operand0, Variadic<AnyType>:$operand1);
328  let assemblyFormat = [{
329    ` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict
330  }];
331}
332
333// Test various mixings of optional operand and result type formatting.
334class FormatOptionalOperandResultOpBase<string suffix, string fmt>
335    : TEST_Op<"format_optional_operand_result_" # suffix # "_op",
336              [AttrSizedOperandSegments]> {
337  let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic);
338  let results = (outs Optional<I64>:$optional_res);
339  let assemblyFormat = fmt;
340}
341
342def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{
343  `(` $optional `:` type($optional) `)` `:` type($optional_res)
344  (`[` $variadic^ `]`)? attr-dict
345}]>;
346
347def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{
348  (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res)
349  (`[` $variadic^ `]`)? attr-dict
350}]>;
351
352// Test optional result type formatting.
353class FormatOptionalResultOpBase<string suffix, string fmt>
354    : TEST_Op<"format_optional_result_" # suffix # "_op",
355              [AttrSizedResultSegments]> {
356  let results = (outs Optional<I64>:$optional, Variadic<I64>:$variadic);
357  let assemblyFormat = fmt;
358}
359def FormatOptionalResultAOp : FormatOptionalResultOpBase<"a", [{
360  (`:` type($optional)^ `->` type($variadic))? attr-dict
361}]>;
362
363def FormatOptionalResultBOp : FormatOptionalResultOpBase<"b", [{
364  (`:` type($optional) `->` type($variadic)^)? attr-dict
365}]>;
366
367def FormatOptionalResultCOp : FormatOptionalResultOpBase<"c", [{
368  (`:` functional-type($optional, $variadic)^)? attr-dict
369}]>;
370
371def FormatOptionalResultDOp
372  : TEST_Op<"format_optional_result_d_op" > {
373  let results = (outs Optional<F80>:$optional);
374  let assemblyFormat = "(`:` type($optional)^)? attr-dict";
375}
376
377def FormatTwoVariadicOperandsNoBuildableTypeOp
378    : TEST_Op<"format_two_variadic_operands_no_buildable_type_op",
379              [AttrSizedOperandSegments]> {
380  let arguments = (ins Variadic<AnyType>:$a,
381                       Variadic<AnyType>:$b);
382  let assemblyFormat = [{
383    `(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)`  attr-dict
384  }];
385}
386
387def FormatInferVariadicTypeFromNonVariadic
388    : TEST_Op<"format_infer_variadic_type_from_non_variadic",
389              [SameOperandsAndResultType]> {
390  let arguments = (ins Variadic<AnyType>:$args);
391  let results = (outs AnyType:$result);
392  let assemblyFormat = "operands attr-dict `:` type($result)";
393}
394
395def FormatOptionalUnitAttr : TEST_Op<"format_optional_unit_attribute"> {
396  let arguments = (ins UnitAttr:$is_optional);
397  let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict";
398}
399
400def FormatOptionalUnitAttrNoElide
401    : TEST_Op<"format_optional_unit_attribute_no_elide"> {
402  let arguments = (ins UnitAttr:$is_optional);
403  let assemblyFormat = "($is_optional^)? attr-dict";
404}
405
406def FormatOptionalUnitProperty : TEST_Op<"format_optional_unit_property"> {
407  let arguments = (ins UnitProp:$is_optional);
408  let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict";
409}
410
411def FormatOptionalUnitPropertyNoElide
412    : TEST_Op<"format_optional_unit_property_no_elide"> {
413  let arguments = (ins UnitProp:$is_optional);
414  let assemblyFormat = "($is_optional^)? attr-dict";
415}
416
417def FormatOptionalEnumAttr : TEST_Op<"format_optional_enum_attr"> {
418  let arguments = (ins OptionalAttr<SomeI64Enum>:$attr);
419  let assemblyFormat = "($attr^)? attr-dict";
420}
421
422def FormatOptionalDefaultAttrs : TEST_Op<"format_optional_default_attrs"> {
423  let arguments = (ins DefaultValuedStrAttr<StrAttr, "default">:$str,
424                       DefaultValuedStrAttr<SymbolNameAttr, "default">:$sym,
425                       DefaultValuedAttr<SomeI64Enum, "SomeI64Enum::case5">:$e);
426  let assemblyFormat = "($str^)? ($sym^)? ($e^)? attr-dict";
427}
428
429def FormatOptionalWithElse : TEST_Op<"format_optional_else"> {
430  let arguments = (ins UnitAttr:$isFirstBranchPresent);
431  let assemblyFormat = "(`then` $isFirstBranchPresent^):(`else`)? attr-dict";
432}
433
434def FormatOptionalPropDict : TEST_Op<"format_optional_prop_dict"> {
435  let arguments = (ins
436    OptionalProp<StringProp>:$a,
437    DefaultValuedProp<I32Prop, "1">:$b);
438  let assemblyFormat = "prop-dict attr-dict";
439}
440
441def FormatCompoundAttr : TEST_Op<"format_compound_attr"> {
442  let arguments = (ins CompoundAttrA:$compound);
443  let assemblyFormat = "$compound attr-dict-with-keyword";
444}
445
446def FormatNestedAttr : TEST_Op<"format_nested_attr"> {
447  let arguments = (ins CompoundAttrNested:$nested);
448  let assemblyFormat = "$nested attr-dict-with-keyword";
449}
450
451def FormatNestedCompoundAttr : TEST_Op<"format_cpmd_nested_attr"> {
452  let arguments = (ins CompoundNestedOuter:$nested);
453  let assemblyFormat = "`nested` $nested attr-dict-with-keyword";
454}
455
456def FormatMaybeEmptyType : TEST_Op<"format_maybe_empty_type"> {
457  let arguments = (ins TestTypeOptionalValueType:$in);
458  let assemblyFormat = "$in `:` type($in) attr-dict";
459}
460
461def FormatQualifiedCompoundAttr : TEST_Op<"format_qual_cpmd_nested_attr"> {
462  let arguments = (ins CompoundNestedOuter:$nested);
463  let assemblyFormat = "`nested` qualified($nested) attr-dict-with-keyword";
464}
465
466def FormatNestedType : TEST_Op<"format_cpmd_nested_type"> {
467  let arguments = (ins CompoundNestedOuterType:$nested);
468  let assemblyFormat = "$nested `nested` type($nested) attr-dict-with-keyword";
469}
470
471def FormatQualifiedNestedType : TEST_Op<"format_qual_cpmd_nested_type"> {
472  let arguments = (ins CompoundNestedOuterType:$nested);
473  let assemblyFormat = "$nested `nested` qualified(type($nested)) attr-dict-with-keyword";
474}
475
476//===----------------------------------------------------------------------===//
477// Custom Directives
478
479def FormatCustomDirectiveOperands
480    : TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> {
481  let arguments = (ins I64:$operand, Optional<I64>:$optOperand,
482                       Variadic<I64>:$varOperands);
483  let assemblyFormat = [{
484    custom<CustomDirectiveOperands>(
485      $operand, $optOperand, $varOperands
486    )
487    attr-dict
488  }];
489}
490
491def FormatCustomDirectiveOperandsAndTypes
492    : TEST_Op<"format_custom_directive_operands_and_types",
493              [AttrSizedOperandSegments]> {
494  let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand,
495                       Variadic<AnyType>:$varOperands);
496  let assemblyFormat = [{
497    custom<CustomDirectiveOperandsAndTypes>(
498      $operand, $optOperand, $varOperands,
499      type($operand), type($optOperand), type($varOperands)
500    )
501    attr-dict
502  }];
503}
504
505def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> {
506  let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$other_regions);
507  let assemblyFormat = [{
508    custom<CustomDirectiveRegions>(
509      $region, $other_regions
510    )
511    attr-dict
512  }];
513}
514
515def FormatCustomDirectiveResults
516    : TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> {
517  let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
518                      Variadic<AnyType>:$varResults);
519  let assemblyFormat = [{
520    custom<CustomDirectiveResults>(
521      type($result), type($optResult), type($varResults)
522    )
523    attr-dict
524  }];
525}
526
527def FormatCustomDirectiveResultsWithTypeRefs
528    : TEST_Op<"format_custom_directive_results_with_type_refs",
529              [AttrSizedResultSegments]> {
530  let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
531                      Variadic<AnyType>:$varResults);
532  let assemblyFormat = [{
533    custom<CustomDirectiveResults>(
534      type($result), type($optResult), type($varResults)
535    )
536    custom<CustomDirectiveWithTypeRefs>(
537      ref(type($result)), ref(type($optResult)), ref(type($varResults))
538    )
539    attr-dict
540  }];
541}
542
543def FormatCustomDirectiveWithOptionalOperandRef
544    : TEST_Op<"format_custom_directive_with_optional_operand_ref"> {
545  let arguments = (ins Optional<I64>:$optOperand);
546  let assemblyFormat = [{
547    ($optOperand^)? `:`
548    custom<CustomDirectiveOptionalOperandRef>(ref($optOperand))
549    attr-dict
550  }];
551}
552
553def FormatCustomDirectiveSuccessors
554    : TEST_Op<"format_custom_directive_successors", [Terminator]> {
555  let successors = (successor AnySuccessor:$successor,
556                              VariadicSuccessor<AnySuccessor>:$successors);
557  let assemblyFormat = [{
558    custom<CustomDirectiveSuccessors>(
559      $successor, $successors
560    )
561    attr-dict
562  }];
563}
564
565def FormatCustomDirectiveAttributes
566    : TEST_Op<"format_custom_directive_attributes"> {
567  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
568  let assemblyFormat = [{
569    custom<CustomDirectiveAttributes>(
570      $attr, $optAttr
571    )
572    attr-dict
573  }];
574}
575
576def FormatCustomDirectiveSpacing
577    : TEST_Op<"format_custom_directive_spacing"> {
578  let arguments = (ins StrAttr:$attr1, StrAttr:$attr2);
579  let assemblyFormat = [{
580    custom<CustomDirectiveSpacing>($attr1)
581    custom<CustomDirectiveSpacing>($attr2)
582    attr-dict
583  }];
584}
585
586def FormatCustomDirectiveAttrDict
587    : TEST_Op<"format_custom_directive_attrdict"> {
588  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
589  let assemblyFormat = [{
590    custom<CustomDirectiveAttrDict>( attr-dict )
591  }];
592}
593
594def FormatLiteralFollowingOptionalGroup
595    : TEST_Op<"format_literal_following_optional_group"> {
596  let arguments = (ins TypeAttr:$type, OptionalAttr<AnyAttr>:$value);
597  let assemblyFormat = "(`(` $value^ `)`)? `:` $type attr-dict";
598}
599
600//===----------------------------------------------------------------------===//
601// AllTypesMatch type inference
602
603def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [
604    AllTypesMatch<["value1", "value2", "result"]>
605  ]> {
606  let arguments = (ins AnyType:$value1, AnyType:$value2);
607  let results = (outs AnyType:$result);
608  let assemblyFormat = "attr-dict $value1 `,` $value2 `:` type($value1)";
609}
610
611def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [
612    AllTypesMatch<["value1", "value2", "result"]>
613  ]> {
614  let arguments = (ins TypedAttrInterface:$value1, AnyType:$value2);
615  let results = (outs AnyType:$result);
616  let assemblyFormat = "attr-dict $value1 `,` $value2";
617}
618
619//===----------------------------------------------------------------------===//
620// TypesMatchWith type inference
621
622def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [
623    TypesMatchWith<"result type matches operand", "value", "result", "$_self">
624  ]> {
625  let arguments = (ins AnyType:$value);
626  let results = (outs AnyType:$result);
627  let assemblyFormat = "attr-dict $value `:` type($value)";
628}
629
630def FormatTypesMatchVariadicOp : TEST_Op<"format_types_match_variadic", [
631    RangedTypesMatchWith<"result type matches operand", "value", "result",
632                         "llvm::make_range($_self.begin(), $_self.end())">
633  ]> {
634  let arguments = (ins Variadic<AnyType>:$value);
635  let results = (outs Variadic<AnyType>:$result);
636  let assemblyFormat = "attr-dict $value `:` type($value)";
637}
638
639def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [
640    TypesMatchWith<"result type matches constant", "value", "result", "$_self">
641  ]> {
642  let arguments = (ins TypedAttrInterface:$value);
643  let results = (outs AnyType:$result);
644  let assemblyFormat = "attr-dict $value";
645}
646
647def FormatTypesMatchContextOp : TEST_Op<"format_types_match_context", [
648    TypesMatchWith<"tuple result type matches operand type", "value", "result",
649        "::mlir::TupleType::get($_ctxt, $_self)">
650  ]> {
651  let arguments = (ins AnyType:$value);
652  let results = (outs AnyType:$result);
653  let assemblyFormat = "attr-dict $value `:` type($value)";
654}
655
656//===----------------------------------------------------------------------===//
657// InferTypeOpInterface type inference in assembly format
658
659def FormatInferTypeOp : TEST_Op<"format_infer_type", [InferTypeOpInterface]> {
660  let results = (outs AnyType);
661  let assemblyFormat = "attr-dict";
662
663  let extraClassDeclaration = [{
664    static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
665          ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
666          ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
667          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
668      inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)});
669      return ::mlir::success();
670    }
671   }];
672}
673
674// Check that formatget supports DeclareOpInterfaceMethods.
675def FormatInferType2Op : TEST_Op<"format_infer_type2", [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
676  let results = (outs AnyType);
677  let assemblyFormat = "attr-dict";
678}
679
680// Base class for testing mixing allOperandTypes, allOperands, and
681// inferResultTypes.
682class FormatInferAllTypesBaseOp<string mnemonic, list<Trait> traits = []>
683    : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {
684  let arguments = (ins Variadic<AnyType>:$args);
685  let results = (outs Variadic<AnyType>:$outs);
686  let extraClassDeclaration = [{
687    static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
688          ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
689          ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
690          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
691      ::mlir::TypeRange operandTypes = operands.getTypes();
692      inferredReturnTypes.assign(operandTypes.begin(), operandTypes.end());
693      return ::mlir::success();
694    }
695   }];
696}
697
698// Test inferReturnTypes is called when allOperandTypes and allOperands is true.
699def FormatInferTypeAllOperandsAndTypesOp
700    : FormatInferAllTypesBaseOp<"format_infer_type_all_operands_and_types"> {
701  let assemblyFormat = "`(` operands `)` attr-dict `:` type(operands)";
702}
703
704// Test inferReturnTypes is called when allOperandTypes is true and there is one
705// ODS operand.
706def FormatInferTypeAllOperandsAndTypesOneOperandOp
707    : FormatInferAllTypesBaseOp<"format_infer_type_all_types_one_operand"> {
708  let assemblyFormat = "`(` $args `)` attr-dict `:` type(operands)";
709}
710
711// Test inferReturnTypes is called when allOperandTypes is true and there are
712// more than one ODS operands.
713def FormatInferTypeAllOperandsAndTypesTwoOperandsOp
714    : FormatInferAllTypesBaseOp<"format_infer_type_all_types_two_operands",
715                                [SameVariadicOperandSize]> {
716  let arguments = (ins Variadic<AnyType>:$args0, Variadic<AnyType>:$args1);
717  let assemblyFormat = "`(` $args0 `)` `(` $args1 `)` attr-dict `:` type(operands)";
718}
719
720// Test inferReturnTypes is called when allOperands is true and operand types
721// are separately specified.
722def FormatInferTypeAllTypesOp
723    : FormatInferAllTypesBaseOp<"format_infer_type_all_types"> {
724  let assemblyFormat = "`(` operands `)` attr-dict `:` type($args)";
725}
726
727// Test inferReturnTypes coupled with regions.
728def FormatInferTypeRegionsOp
729    : TEST_Op<"format_infer_type_regions", [InferTypeOpInterface]> {
730  let results = (outs Variadic<AnyType>:$outs);
731  let regions = (region AnyRegion:$region);
732  let assemblyFormat = "$region attr-dict";
733  let extraClassDeclaration = [{
734    static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
735          ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
736          ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
737          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
738      if (regions.empty())
739        return ::mlir::failure();
740      auto types = regions.front()->getArgumentTypes();
741      inferredReturnTypes.assign(types.begin(), types.end());
742      return ::mlir::success();
743    }
744  }];
745}
746
747// Test inferReturnTypes coupled with variadic operands (operandSegmentSizes).
748def FormatInferTypeVariadicOperandsOp
749    : TEST_Op<"format_infer_type_variadic_operands",
750              [InferTypeOpInterface, AttrSizedOperandSegments]> {
751  let arguments = (ins Variadic<I32>:$a, Variadic<I64>:$b);
752  let results = (outs Variadic<AnyType>:$outs);
753  let assemblyFormat = "`(` $a `:` type($a) `)` `(` $b `:` type($b) `)` attr-dict";
754  let extraClassDeclaration = [{
755    static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
756          ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
757          ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
758          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
759      FormatInferTypeVariadicOperandsOpAdaptor adaptor(
760          operands, attributes, *properties.as<Properties *>(), {});
761      auto aTypes = adaptor.getA().getTypes();
762      auto bTypes = adaptor.getB().getTypes();
763      inferredReturnTypes.append(aTypes.begin(), aTypes.end());
764      inferredReturnTypes.append(bTypes.begin(), bTypes.end());
765      return ::mlir::success();
766    }
767  }];
768}
769
770#endif  // TEST_OPS_SYNTAX
771