| //===-- TestOpsSyntax.td - Operations for testing syntax ---*- tablegen -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef TEST_OPS_SYNTAX | |
| #define TEST_OPS_SYNTAX | |
| include "TestAttrDefs.td" | |
| include "TestDialect.td" | |
| include "TestTypeDefs.td" | |
| include "mlir/Interfaces/InferTypeOpInterface.td" | |
| include "mlir/IR/OpBase.td" | |
| class TEST_Op<string mnemonic, list<Trait> traits = []> : | |
| Op<Test_Dialect, mnemonic, traits>; | |
| def WrappingRegionOp : TEST_Op<"wrapping_region", | |
| [SingleBlockImplicitTerminator<"TestReturnOp">]> { | |
| let summary = "wrapping region operation"; | |
| let description = [{ | |
| Test op wrapping another op in a region, to test calling | |
| parseGenericOperation from the custom parser. | |
| }]; | |
| let results = (outs Variadic<AnyType>); | |
| let regions = (region SizedRegion<1>:$region); | |
| let hasCustomAssemblyFormat = 1; | |
| } | |
| def PrettyPrintedRegionOp : TEST_Op<"pretty_printed_region", | |
| [SingleBlockImplicitTerminator<"TestReturnOp">]> { | |
| let summary = "pretty_printed_region operation"; | |
| let description = [{ | |
| Test-op can be printed either in a "pretty" or "non-pretty" way based on | |
| some criteria. The custom parser parsers both the versions while testing | |
| APIs: parseCustomOperationName & parseGenericOperationAfterOpName. | |
| }]; | |
| let arguments = (ins | |
| AnyType:$input1, | |
| AnyType:$input2 | |
| ); | |
| let results = (outs AnyType); | |
| let regions = (region SizedRegion<1>:$region); | |
| let hasCustomAssemblyFormat = 1; | |
| } | |
| def PolyForOp : TEST_Op<"polyfor", [OpAsmOpInterface]> { | |
| let summary = "polyfor operation"; | |
| let description = [{ | |
| Test op with multiple region arguments, each argument of index type. | |
| }]; | |
| let extraClassDeclaration = [{ | |
| void getAsmBlockArgumentNames(mlir::Region ®ion, | |
| mlir::OpAsmSetValueNameFn setNameFn); | |
| }]; | |
| let regions = (region SizedRegion<1>:$region); | |
| let hasCustomAssemblyFormat = 1; | |
| } | |
| def TestAttrWithLoc : TEST_Op<"attr_with_loc"> { | |
| let summary = "op's attribute has a location"; | |
| let arguments = (ins AnyAttr:$loc, AnyAttr:$value); | |
| let assemblyFormat = "`(` $value `` custom<OptionalLoc>($loc) `)` attr-dict"; | |
| } | |
| def ParseCustomOperationNameAPI : TEST_Op<"parse_custom_operation_name_api"> { | |
| let summary = "noop that exercises the parseCustomOperationName API"; | |
| let arguments = (ins StrAttr:$name); | |
| let assemblyFormat = "`(` custom<CustomOperationNameEntry>($name) `)` attr-dict"; | |
| } | |
| // ----- | |
| // This is used to test that the fallback for a custom op's parser and printer | |
| // is the dialect parser and printer hooks. | |
| def CustomFormatFallbackOp : TEST_Op<"dialect_custom_format_fallback">; | |
| // Ops related to OIList primitive | |
| def OIListTrivial : TEST_Op<"oilist_with_keywords_only"> { | |
| let arguments = (ins UnitAttr:$keyword, UnitAttr:$otherKeyword, | |
| UnitAttr:$diffNameUnitAttrKeyword); | |
| let assemblyFormat = [{ | |
| oilist( `keyword` $keyword | |
| | `otherKeyword` $otherKeyword | |
| | `thirdKeyword` $diffNameUnitAttrKeyword) attr-dict | |
| }]; | |
| } | |
| // Ops related to OIList primitive | |
| def OIListTrivialProperties : TEST_Op<"oilist_with_keywords_only_properties"> { | |
| let arguments = (ins UnitProp:$keyword, UnitProp:$otherKeyword, | |
| UnitProp:$diffNameUnitPropKeyword); | |
| let assemblyFormat = [{ | |
| oilist( `keyword` $keyword | |
| | `otherKeyword` $otherKeyword | |
| | `thirdKeyword` $diffNameUnitPropKeyword) attr-dict | |
| }]; | |
| } | |
| def OIListSimple : TEST_Op<"oilist_with_simple_args", [AttrSizedOperandSegments]> { | |
| let arguments = (ins Optional<AnyType>:$arg0, | |
| Optional<AnyType>:$arg1, | |
| Optional<AnyType>:$arg2); | |
| let assemblyFormat = [{ | |
| oilist( `keyword` $arg0 `:` type($arg0) | |
| | `otherKeyword` $arg1 `:` type($arg1) | |
| | `thirdKeyword` $arg2 `:` type($arg2) ) attr-dict | |
| }]; | |
| } | |
| def OIListVariadic : TEST_Op<"oilist_variadic_with_parens", [AttrSizedOperandSegments]> { | |
| let arguments = (ins Variadic<AnyType>:$arg0, | |
| Variadic<AnyType>:$arg1, | |
| Variadic<AnyType>:$arg2); | |
| let assemblyFormat = [{ | |
| oilist( `keyword` `(` $arg0 `:` type($arg0) `)` | |
| | `otherKeyword` `(` $arg1 `:` type($arg1) `)` | |
| | `thirdKeyword` `(` $arg2 `:` type($arg2) `)`) attr-dict | |
| }]; | |
| } | |
| def OIListCustom : TEST_Op<"oilist_custom", [AttrSizedOperandSegments]> { | |
| let arguments = (ins Variadic<AnyType>:$arg0, | |
| Optional<I32>:$optOperand, | |
| UnitAttr:$nowait); | |
| let assemblyFormat = [{ | |
| oilist( `private` `(` $arg0 `:` type($arg0) `)` | |
| | `reduction` custom<CustomOptionalOperand>($optOperand) | |
| | `nowait` $nowait | |
| ) attr-dict | |
| }]; | |
| } | |
| def OIListWithSeparator : TEST_Op<"oilist_with_separator"> { | |
| let arguments = (ins UnitAttr:$keyword, UnitAttr:$otherKeyword, | |
| UnitAttr:$diffNameUnitAttrKeyword); | |
| let assemblyFormat = [{ | |
| oilist<`,`>( `keyword` $keyword | |
| | `otherKeyword` $otherKeyword | |
| | `thirdKeyword` $diffNameUnitAttrKeyword) attr-dict | |
| }]; | |
| } | |
| def OIListOptionalAttr : TEST_Op<"oilist_optional_attr"> { | |
| let arguments = (ins UnitAttr:$keyword, | |
| OptionalAttr<CompoundAttrNested>:$nested); | |
| let assemblyFormat = [{ | |
| oilist( `keyword` $keyword | |
| | `nested` $nested) attr-dict | |
| }]; | |
| } | |
| def OIListAllowedLiteral : TEST_Op<"oilist_allowed_literal"> { | |
| let assemblyFormat = [{ | |
| oilist( `foo` | `bar` ) `buzz` attr-dict | |
| }]; | |
| } | |
| def TestEllipsisOp : TEST_Op<"ellipsis"> { | |
| let arguments = (ins Variadic<AnyType>:$operands, UnitAttr:$variadic); | |
| let assemblyFormat = [{ | |
| `(` $operands (`...` $variadic^)? `)` attr-dict `:` type($operands) `...` | |
| }]; | |
| } | |
| def ElseAnchorOp : TEST_Op<"else_anchor"> { | |
| let arguments = (ins Optional<AnyType>:$a); | |
| let assemblyFormat = "`(` (`?`) : (`` $a^ `:` type($a))? `)` attr-dict"; | |
| } | |
| // This is used to test that the default dialect is not elided when printing an | |
| // op with dots in the name to avoid parsing ambiguity. | |
| def OpWithDotInNameOp : TEST_Op<"op.with_dot_in_name"> { | |
| let assemblyFormat = "attr-dict"; | |
| } | |
| // -------------- | |
| //===----------------------------------------------------------------------===// | |
| // Test Op Asm Format | |
| //===----------------------------------------------------------------------===// | |
| def FormatLiteralOp : TEST_Op<"format_literal_op"> { | |
| let assemblyFormat = [{ | |
| `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)` | |
| `?` `+` `*` `{` `\n` `}` attr-dict | |
| }]; | |
| } | |
| // Test that inherent and discardable attributes use separate dictionaries. | |
| def FormatAttrOp : TEST_Op<"format_attr_op"> { | |
| let arguments = (ins I64Attr:$attr); | |
| let assemblyFormat = "$attr attr-dict"; | |
| } | |
| // Test that we elide optional attributes that are within the syntax. | |
| def FormatOptAttrAOp : TEST_Op<"format_opt_attr_op_a"> { | |
| let arguments = (ins OptionalAttr<I64Attr>:$opt_attr); | |
| let assemblyFormat = "(`(` $opt_attr^ `)` )? attr-dict"; | |
| } | |
| def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> { | |
| let arguments = (ins OptionalAttr<I64Attr>:$opt_attr); | |
| let assemblyFormat = "($opt_attr^)? attr-dict"; | |
| } | |
| // Test that we format symbol name attributes properly. | |
| def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> { | |
| let arguments = (ins SymbolNameAttr:$attr); | |
| let assemblyFormat = "$attr attr-dict"; | |
| } | |
| // Test that we format optional symbol name attributes properly. | |
| def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> { | |
| let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr); | |
| let assemblyFormat = "($opt_attr^)? attr-dict"; | |
| } | |
| // Test that we format optional symbol reference attributes properly. | |
| def FormatOptSymbolRefAttrOp : TEST_Op<"format_opt_symbol_ref_attr_op"> { | |
| let arguments = (ins OptionalAttr<SymbolRefAttr>:$opt_attr); | |
| let assemblyFormat = "($opt_attr^)? attr-dict"; | |
| } | |
| // Test that we elide attributes that are within the syntax. | |
| def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> { | |
| let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr); | |
| let assemblyFormat = "prop-dict attr-dict-with-keyword"; | |
| } | |
| // Test that we don't need to provide types in the format if they are buildable. | |
| def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> { | |
| let arguments = (ins I64:$buildable); | |
| let results = (outs I64:$buildable_res); | |
| let assemblyFormat = "$buildable attr-dict"; | |
| } | |
| // Test various mixings of region formatting. | |
| class FormatRegionBase<string suffix, string fmt> | |
| : TEST_Op<"format_region_" # suffix # "_op"> { | |
| let regions = (region AnyRegion:$region); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatRegionAOp : FormatRegionBase<"a", [{ | |
| regions attr-dict | |
| }]>; | |
| def FormatRegionBOp : FormatRegionBase<"b", [{ | |
| $region attr-dict | |
| }]>; | |
| def FormatRegionCOp : FormatRegionBase<"c", [{ | |
| (`region` $region^)? attr-dict | |
| }]>; | |
| class FormatVariadicRegionBase<string suffix, string fmt> | |
| : TEST_Op<"format_variadic_region_" # suffix # "_op"> { | |
| let regions = (region VariadicRegion<AnyRegion>:$regions); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{ | |
| $regions attr-dict | |
| }]>; | |
| def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{ | |
| ($regions^ `found_regions`)? attr-dict | |
| }]>; | |
| class FormatRegionImplicitTerminatorBase<string suffix, string fmt> | |
| : TEST_Op<"format_implicit_terminator_region_" # suffix # "_op", | |
| [SingleBlockImplicitTerminator<"TestReturnOp">]> { | |
| let regions = (region AnyRegion:$region); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatFormatRegionImplicitTerminatorAOp | |
| : FormatRegionImplicitTerminatorBase<"a", [{ | |
| $region attr-dict | |
| }]>; | |
| // Test various mixings of result type formatting. | |
| class FormatResultBase<string suffix, string fmt> | |
| : TEST_Op<"format_result_" # suffix # "_op"> { | |
| let results = (outs I64:$buildable_res, AnyMemRef:$result); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatResultAOp : FormatResultBase<"a", [{ | |
| type($result) attr-dict | |
| }]>; | |
| def FormatResultBOp : FormatResultBase<"b", [{ | |
| type(results) attr-dict | |
| }]>; | |
| def FormatResultCOp : FormatResultBase<"c", [{ | |
| functional-type($buildable_res, $result) attr-dict | |
| }]>; | |
| def FormatVariadicResult : TEST_Op<"format_variadic_result"> { | |
| let results = (outs Variadic<I64>:$result); | |
| let assemblyFormat = [{ `:` type($result) attr-dict}]; | |
| } | |
| def FormatMultipleVariadicResults : TEST_Op<"format_multiple_variadic_results", | |
| [AttrSizedResultSegments]> { | |
| let results = (outs Variadic<I64>:$result0, Variadic<AnyType>:$result1); | |
| let assemblyFormat = [{ | |
| `:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict | |
| }]; | |
| } | |
| // Test various mixings of operand type formatting. | |
| class FormatOperandBase<string suffix, string fmt> | |
| : TEST_Op<"format_operand_" # suffix # "_op"> { | |
| let arguments = (ins I64:$buildable, AnyMemRef:$operand); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatOperandAOp : FormatOperandBase<"a", [{ | |
| operands `:` type(operands) attr-dict | |
| }]>; | |
| def FormatOperandBOp : FormatOperandBase<"b", [{ | |
| operands `:` type($operand) attr-dict | |
| }]>; | |
| def FormatOperandCOp : FormatOperandBase<"c", [{ | |
| $buildable `,` $operand `:` type(operands) attr-dict | |
| }]>; | |
| def FormatOperandDOp : FormatOperandBase<"d", [{ | |
| $buildable `,` $operand `:` type($operand) attr-dict | |
| }]>; | |
| def FormatOperandEOp : FormatOperandBase<"e", [{ | |
| $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict | |
| }]>; | |
| def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> { | |
| let successors = (successor VariadicSuccessor<AnySuccessor>:$targets); | |
| let assemblyFormat = "$targets attr-dict"; | |
| } | |
| def FormatVariadicOperand : TEST_Op<"format_variadic_operand"> { | |
| let arguments = (ins Variadic<I64>:$operand); | |
| let assemblyFormat = [{ $operand `:` type($operand) attr-dict}]; | |
| } | |
| def FormatVariadicOfVariadicOperand | |
| : TEST_Op<"format_variadic_of_variadic_operand"> { | |
| let arguments = (ins | |
| VariadicOfVariadic<I64, "operand_segments">:$operand, | |
| DenseI32ArrayAttr:$operand_segments | |
| ); | |
| let assemblyFormat = [{ $operand `:` type($operand) attr-dict}]; | |
| } | |
| def FormatMultipleVariadicOperands : | |
| TEST_Op<"format_multiple_variadic_operands", [AttrSizedOperandSegments]> { | |
| let arguments = (ins Variadic<I64>:$operand0, Variadic<AnyType>:$operand1); | |
| let assemblyFormat = [{ | |
| ` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict | |
| }]; | |
| } | |
| // Test various mixings of optional operand and result type formatting. | |
| class FormatOptionalOperandResultOpBase<string suffix, string fmt> | |
| : TEST_Op<"format_optional_operand_result_" # suffix # "_op", | |
| [AttrSizedOperandSegments]> { | |
| let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic); | |
| let results = (outs Optional<I64>:$optional_res); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{ | |
| `(` $optional `:` type($optional) `)` `:` type($optional_res) | |
| (`[` $variadic^ `]`)? attr-dict | |
| }]>; | |
| def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{ | |
| (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res) | |
| (`[` $variadic^ `]`)? attr-dict | |
| }]>; | |
| // Test optional result type formatting. | |
| class FormatOptionalResultOpBase<string suffix, string fmt> | |
| : TEST_Op<"format_optional_result_" # suffix # "_op", | |
| [AttrSizedResultSegments]> { | |
| let results = (outs Optional<I64>:$optional, Variadic<I64>:$variadic); | |
| let assemblyFormat = fmt; | |
| } | |
| def FormatOptionalResultAOp : FormatOptionalResultOpBase<"a", [{ | |
| (`:` type($optional)^ `->` type($variadic))? attr-dict | |
| }]>; | |
| def FormatOptionalResultBOp : FormatOptionalResultOpBase<"b", [{ | |
| (`:` type($optional) `->` type($variadic)^)? attr-dict | |
| }]>; | |
| def FormatOptionalResultCOp : FormatOptionalResultOpBase<"c", [{ | |
| (`:` functional-type($optional, $variadic)^)? attr-dict | |
| }]>; | |
| def FormatOptionalResultDOp | |
| : TEST_Op<"format_optional_result_d_op" > { | |
| let results = (outs Optional<F80>:$optional); | |
| let assemblyFormat = "(`:` type($optional)^)? attr-dict"; | |
| } | |
| def FormatTwoVariadicOperandsNoBuildableTypeOp | |
| : TEST_Op<"format_two_variadic_operands_no_buildable_type_op", | |
| [AttrSizedOperandSegments]> { | |
| let arguments = (ins Variadic<AnyType>:$a, | |
| Variadic<AnyType>:$b); | |
| let assemblyFormat = [{ | |
| `(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)` attr-dict | |
| }]; | |
| } | |
| def FormatInferVariadicTypeFromNonVariadic | |
| : TEST_Op<"format_infer_variadic_type_from_non_variadic", | |
| [SameOperandsAndResultType]> { | |
| let arguments = (ins Variadic<AnyType>:$args); | |
| let results = (outs AnyType:$result); | |
| let assemblyFormat = "operands attr-dict `:` type($result)"; | |
| } | |
| def FormatOptionalUnitAttr : TEST_Op<"format_optional_unit_attribute"> { | |
| let arguments = (ins UnitAttr:$is_optional); | |
| let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict"; | |
| } | |
| def FormatOptionalUnitAttrNoElide | |
| : TEST_Op<"format_optional_unit_attribute_no_elide"> { | |
| let arguments = (ins UnitAttr:$is_optional); | |
| let assemblyFormat = "($is_optional^)? attr-dict"; | |
| } | |
| def FormatOptionalUnitProperty : TEST_Op<"format_optional_unit_property"> { | |
| let arguments = (ins UnitProp:$is_optional); | |
| let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict"; | |
| } | |
| def FormatOptionalUnitPropertyNoElide | |
| : TEST_Op<"format_optional_unit_property_no_elide"> { | |
| let arguments = (ins UnitProp:$is_optional); | |
| let assemblyFormat = "($is_optional^)? attr-dict"; | |
| } | |
| def FormatOptionalEnumAttr : TEST_Op<"format_optional_enum_attr"> { | |
| let arguments = (ins OptionalAttr<SomeI64Enum>:$attr); | |
| let assemblyFormat = "($attr^)? attr-dict"; | |
| } | |
| def FormatOptionalDefaultAttrs : TEST_Op<"format_optional_default_attrs"> { | |
| let arguments = (ins DefaultValuedStrAttr<StrAttr, "default">:$str, | |
| DefaultValuedStrAttr<SymbolNameAttr, "default">:$sym, | |
| DefaultValuedAttr<SomeI64Enum, "SomeI64Enum::case5">:$e); | |
| let assemblyFormat = "($str^)? ($sym^)? ($e^)? attr-dict"; | |
| } | |
| def FormatOptionalDefaultEnumAttrs : TEST_Op<"format_optional_default_enum_attr"> { | |
| let arguments = (ins DefaultValuedEnumAttr<SomeI64Enum, I64Case5>:$e); | |
| let assemblyFormat = "($e^)? attr-dict"; | |
| } | |
| // Two adjacent optional enum props with different enum types, to exercise | |
| // constrained keyword parsing (parseOptionalKeyword with keyword list). | |
| def TestEnumPropDefault : EnumProp<TestEnum> { | |
| let defaultValue = TestEnum.cppType # "::First"; | |
| } | |
| def TestOtherEnumPropDefault : EnumProp<TestOtherEnum> { | |
| let defaultValue = TestOtherEnum.cppType # "::Dog"; | |
| } | |
| def OpWithTwoDefaultEnumProps : TEST_Op<"op_with_two_default_enum_props"> { | |
| let arguments = (ins | |
| TestEnumPropDefault:$value1, | |
| TestOtherEnumPropDefault:$value2); | |
| let assemblyFormat = "($value1^)? ($value2^)? attr-dict"; | |
| } | |
| def TestBitEnumPropDefault : EnumProp<TestBitEnum> { | |
| let defaultValue = TestBitEnum.cppType # "::Read"; | |
| } | |
| def TestBitEnumVerticalBarPropDefault : EnumProp<TestBitEnumVerticalBar> { | |
| let defaultValue = TestBitEnumVerticalBar.cppType # "::User"; | |
| } | |
| def OpWithTwoDefaultBitEnumProps : TEST_Op<"op_with_two_default_bit_enum_props"> { | |
| let arguments = (ins | |
| TestBitEnumPropDefault:$value1, | |
| TestBitEnumVerticalBarPropDefault:$value2); | |
| let assemblyFormat = "($value1^)? ($value2^)? attr-dict"; | |
| } | |
| def FormatOptionalWithElse : TEST_Op<"format_optional_else"> { | |
| let arguments = (ins UnitAttr:$isFirstBranchPresent); | |
| let assemblyFormat = "(`then` $isFirstBranchPresent^):(`else`)? attr-dict"; | |
| } | |
| def FormatOptionalPropDict : TEST_Op<"format_optional_prop_dict"> { | |
| let arguments = (ins | |
| OptionalProp<StringProp>:$a, | |
| DefaultValuedProp<I32Prop, "1">:$b); | |
| let assemblyFormat = "prop-dict attr-dict"; | |
| } | |
| def FormatCompoundAttr : TEST_Op<"format_compound_attr"> { | |
| let arguments = (ins CompoundAttrA:$compound); | |
| let assemblyFormat = "$compound attr-dict-with-keyword"; | |
| } | |
| def FormatNestedAttr : TEST_Op<"format_nested_attr"> { | |
| let arguments = (ins CompoundAttrNested:$nested); | |
| let assemblyFormat = "$nested attr-dict-with-keyword"; | |
| } | |
| def FormatNestedCompoundAttr : TEST_Op<"format_cpmd_nested_attr"> { | |
| let arguments = (ins CompoundNestedOuter:$nested); | |
| let assemblyFormat = "`nested` $nested attr-dict-with-keyword"; | |
| } | |
| def FormatMaybeEmptyType : TEST_Op<"format_maybe_empty_type"> { | |
| let arguments = (ins TestTypeOptionalValueType:$in); | |
| let assemblyFormat = "$in `:` type($in) attr-dict"; | |
| } | |
| def FormatQualifiedCompoundAttr : TEST_Op<"format_qual_cpmd_nested_attr"> { | |
| let arguments = (ins CompoundNestedOuter:$nested); | |
| let assemblyFormat = "`nested` qualified($nested) attr-dict-with-keyword"; | |
| } | |
| def FormatNestedType : TEST_Op<"format_cpmd_nested_type"> { | |
| let arguments = (ins CompoundNestedOuterType:$nested); | |
| let assemblyFormat = "$nested `nested` type($nested) attr-dict-with-keyword"; | |
| } | |
| def FormatQualifiedNestedType : TEST_Op<"format_qual_cpmd_nested_type"> { | |
| let arguments = (ins CompoundNestedOuterType:$nested); | |
| let assemblyFormat = "$nested `nested` qualified(type($nested)) attr-dict-with-keyword"; | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // Custom Directives | |
| //===----------------------------------------------------------------------===// | |
| def FormatCustomDirectiveOperands | |
| : TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> { | |
| let arguments = (ins I64:$operand, Optional<I64>:$optOperand, | |
| Variadic<I64>:$varOperands); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveOperands>( | |
| $operand, $optOperand, $varOperands | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveOperandsAndTypes | |
| : TEST_Op<"format_custom_directive_operands_and_types", | |
| [AttrSizedOperandSegments]> { | |
| let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand, | |
| Variadic<AnyType>:$varOperands); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveOperandsAndTypes>( | |
| $operand, $optOperand, $varOperands, | |
| type($operand), type($optOperand), type($varOperands) | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> { | |
| let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$other_regions); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveRegions>( | |
| $region, $other_regions | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveResults | |
| : TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> { | |
| let results = (outs AnyType:$result, Optional<AnyType>:$optResult, | |
| Variadic<AnyType>:$varResults); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveResults>( | |
| type($result), type($optResult), type($varResults) | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveResultsWithTypeRefs | |
| : TEST_Op<"format_custom_directive_results_with_type_refs", | |
| [AttrSizedResultSegments]> { | |
| let results = (outs AnyType:$result, Optional<AnyType>:$optResult, | |
| Variadic<AnyType>:$varResults); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveResults>( | |
| type($result), type($optResult), type($varResults) | |
| ) | |
| custom<CustomDirectiveWithTypeRefs>( | |
| ref(type($result)), ref(type($optResult)), ref(type($varResults)) | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveWithOptionalOperandRef | |
| : TEST_Op<"format_custom_directive_with_optional_operand_ref"> { | |
| let arguments = (ins Optional<I64>:$optOperand); | |
| let assemblyFormat = [{ | |
| ($optOperand^)? `:` | |
| custom<CustomDirectiveOptionalOperandRef>(ref($optOperand)) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveSuccessors | |
| : TEST_Op<"format_custom_directive_successors", [Terminator]> { | |
| let successors = (successor AnySuccessor:$successor, | |
| VariadicSuccessor<AnySuccessor>:$successors); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveSuccessors>( | |
| $successor, $successors | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveAttributes | |
| : TEST_Op<"format_custom_directive_attributes"> { | |
| let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveAttributes>( | |
| $attr, $optAttr | |
| ) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveSpacing | |
| : TEST_Op<"format_custom_directive_spacing"> { | |
| let arguments = (ins StrAttr:$attr1, StrAttr:$attr2); | |
| let assemblyFormat = [{ | |
| custom<CustomDirectiveSpacing>($attr1) | |
| custom<CustomDirectiveSpacing>($attr2) | |
| attr-dict | |
| }]; | |
| } | |
| def FormatCustomDirectiveAttrDict | |
| : TEST_Op<"format_custom_directive_attrdict"> { | |
| let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr); | |
| let assemblyFormat = [{ | |
| prop-dict custom<CustomDirectiveAttrDict>( attr-dict ) | |
| }]; | |
| } | |
| def FormatLiteralFollowingOptionalGroup | |
| : TEST_Op<"format_literal_following_optional_group"> { | |
| let arguments = (ins TypeAttr:$type, OptionalAttr<AnyAttr>:$value); | |
| let assemblyFormat = "(`(` $value^ `)`)? `:` $type attr-dict"; | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // AllTypesMatch type inference | |
| //===----------------------------------------------------------------------===// | |
| def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [ | |
| AllTypesMatch<["value1", "value2", "result"]> | |
| ]> { | |
| let arguments = (ins AnyType:$value1, AnyType:$value2); | |
| let results = (outs AnyType:$result); | |
| let assemblyFormat = "attr-dict $value1 `,` $value2 `:` type($value1)"; | |
| } | |
| def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [ | |
| AllTypesMatch<["value1", "value2", "result"]> | |
| ]> { | |
| let arguments = (ins TypedAttrInterface:$value1, AnyType:$value2); | |
| let results = (outs AnyType:$result); | |
| let assemblyFormat = "attr-dict $value1 `,` $value2"; | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // TypesMatchWith type inference | |
| //===----------------------------------------------------------------------===// | |
| def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [ | |
| TypesMatchWith<"result type matches operand", "value", "result", "$_self"> | |
| ]> { | |
| let arguments = (ins AnyType:$value); | |
| let results = (outs AnyType:$result); | |
| let assemblyFormat = "attr-dict $value `:` type($value)"; | |
| } | |
| def FormatTypesMatchVariadicOp : TEST_Op<"format_types_match_variadic", [ | |
| RangedTypesMatchWith<"result type matches operand", "value", "result", | |
| "llvm::make_range($_self.begin(), $_self.end())"> | |
| ]> { | |
| let arguments = (ins Variadic<AnyType>:$value); | |
| let results = (outs Variadic<AnyType>:$result); | |
| let assemblyFormat = "attr-dict $value `:` type($value)"; | |
| } | |
| def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [ | |
| TypesMatchWith<"result type matches constant", "value", "result", "$_self"> | |
| ]> { | |
| let arguments = (ins TypedAttrInterface:$value); | |
| let results = (outs AnyType:$result); | |
| let assemblyFormat = "attr-dict $value"; | |
| } | |
| def FormatTypesMatchContextOp : TEST_Op<"format_types_match_context", [ | |
| TypesMatchWith<"tuple result type matches operand type", "value", "result", | |
| "::mlir::TupleType::get($_ctxt, $_self)"> | |
| ]> { | |
| let arguments = (ins AnyType:$value); | |
| let results = (outs AnyType:$result); | |
| let assemblyFormat = "attr-dict $value `:` type($value)"; | |
| } | |
| def FormatTypesMatchOptionalOp : TEST_Op<"format_types_match_optional", [ | |
| OptionalTypesMatchWith<"optional type matches result", | |
| "result", "optional", "$_self"> | |
| ]> { | |
| let arguments = (ins Optional<AnyType>:$optional); | |
| let results = (outs Optional<AnyType>:$result); | |
| let assemblyFormat = [{ | |
| (`(` $optional^ `:` type($result) `)`)? attr-dict | |
| }]; | |
| } | |
| def FormatOptionalOperandTypeOp | |
| : TEST_Op<"format_optional_operand_type"> { | |
| let arguments = (ins Optional<AnyType>:$optional); | |
| let assemblyFormat = [{ | |
| (`(` $optional^ `)`)? | |
| (`:` type($optional)^)? | |
| attr-dict | |
| }]; | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // InferTypeOpInterface type inference in assembly format | |
| //===----------------------------------------------------------------------===// | |
| def FormatInferTypeOp : TEST_Op<"format_infer_type", [InferTypeOpInterface]> { | |
| let results = (outs AnyType); | |
| let assemblyFormat = "attr-dict"; | |
| let extraClassDeclaration = [{ | |
| static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, | |
| ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, | |
| ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions, | |
| ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) { | |
| inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)}); | |
| return ::mlir::success(); | |
| } | |
| }]; | |
| } | |
| // Check that formatget supports DeclareOpInterfaceMethods. | |
| def FormatInferType2Op : TEST_Op<"format_infer_type2", [DeclareOpInterfaceMethods<InferTypeOpInterface>]> { | |
| let results = (outs AnyType); | |
| let assemblyFormat = "attr-dict"; | |
| } | |
| // Base class for testing mixing allOperandTypes, allOperands, and | |
| // inferResultTypes. | |
| class FormatInferAllTypesBaseOp<string mnemonic, list<Trait> traits = []> | |
| : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> { | |
| let arguments = (ins Variadic<AnyType>:$args); | |
| let results = (outs Variadic<AnyType>:$outs); | |
| let extraClassDeclaration = [{ | |
| static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, | |
| ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, | |
| ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions, | |
| ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) { | |
| ::mlir::TypeRange operandTypes = operands.getTypes(); | |
| inferredReturnTypes.assign(operandTypes.begin(), operandTypes.end()); | |
| return ::mlir::success(); | |
| } | |
| }]; | |
| } | |
| // Test inferReturnTypes is called when allOperandTypes and allOperands is true. | |
| def FormatInferTypeAllOperandsAndTypesOp | |
| : FormatInferAllTypesBaseOp<"format_infer_type_all_operands_and_types"> { | |
| let assemblyFormat = "`(` operands `)` attr-dict `:` type(operands)"; | |
| } | |
| // Test inferReturnTypes is called when allOperandTypes is true and there is one | |
| // ODS operand. | |
| def FormatInferTypeAllOperandsAndTypesOneOperandOp | |
| : FormatInferAllTypesBaseOp<"format_infer_type_all_types_one_operand"> { | |
| let assemblyFormat = "`(` $args `)` attr-dict `:` type(operands)"; | |
| } | |
| // Test inferReturnTypes is called when allOperandTypes is true and there are | |
| // more than one ODS operands. | |
| def FormatInferTypeAllOperandsAndTypesTwoOperandsOp | |
| : FormatInferAllTypesBaseOp<"format_infer_type_all_types_two_operands", | |
| [SameVariadicOperandSize]> { | |
| let arguments = (ins Variadic<AnyType>:$args0, Variadic<AnyType>:$args1); | |
| let assemblyFormat = "`(` $args0 `)` `(` $args1 `)` attr-dict `:` type(operands)"; | |
| } | |
| // Test inferReturnTypes is called when allOperands is true and operand types | |
| // are separately specified. | |
| def FormatInferTypeAllTypesOp | |
| : FormatInferAllTypesBaseOp<"format_infer_type_all_types"> { | |
| let assemblyFormat = "`(` operands `)` attr-dict `:` type($args)"; | |
| } | |
| // Test inferReturnTypes coupled with regions. | |
| def FormatInferTypeRegionsOp | |
| : TEST_Op<"format_infer_type_regions", [InferTypeOpInterface]> { | |
| let results = (outs Variadic<AnyType>:$outs); | |
| let regions = (region AnyRegion:$region); | |
| let assemblyFormat = "$region attr-dict"; | |
| let extraClassDeclaration = [{ | |
| static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, | |
| ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, | |
| ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions, | |
| ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) { | |
| if (regions.empty()) | |
| return ::mlir::failure(); | |
| auto types = regions.front()->getArgumentTypes(); | |
| inferredReturnTypes.assign(types.begin(), types.end()); | |
| return ::mlir::success(); | |
| } | |
| }]; | |
| } | |
| // Test inferReturnTypes coupled with variadic operands (operandSegmentSizes). | |
| def FormatInferTypeVariadicOperandsOp | |
| : TEST_Op<"format_infer_type_variadic_operands", | |
| [InferTypeOpInterface, AttrSizedOperandSegments]> { | |
| let arguments = (ins Variadic<I32>:$a, Variadic<I64>:$b); | |
| let results = (outs Variadic<AnyType>:$outs); | |
| let assemblyFormat = "`(` $a `:` type($a) `)` `(` $b `:` type($b) `)` attr-dict"; | |
| let extraClassDeclaration = [{ | |
| static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, | |
| ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, | |
| ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions, | |
| ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) { | |
| FormatInferTypeVariadicOperandsOpAdaptor adaptor( | |
| operands, attributes, *properties.as<Properties *>(), {}); | |
| auto aTypes = adaptor.getA().getTypes(); | |
| auto bTypes = adaptor.getB().getTypes(); | |
| inferredReturnTypes.append(aTypes.begin(), aTypes.end()); | |
| inferredReturnTypes.append(bTypes.begin(), bTypes.end()); | |
| return ::mlir::success(); | |
| } | |
| }]; | |
| } | |
| def VariadicArgsTypesSplit : TEST_Op<"variadic_args_types_split"> { | |
| let arguments = (ins StrAttr:$str, Variadic<AnyType>:$args); | |
| let assemblyFormat = "$str (`,` $args^)? attr-dict (`:` type($args)^)?"; | |
| } | |
| #endif // TEST_OPS_SYNTAX |