xref: /llvm-project/mlir/test/mlir-tblgen/op-attribute.td (revision db791b278a414fb6df1acc1799adcf11d8fb9169)
1// RUN: mlir-tblgen -gen-op-decls -I %S/../../include %s | FileCheck %s --check-prefix=DECL
2// RUN: mlir-tblgen -gen-op-defs -I %S/../../include %s | FileCheck %s --check-prefix=DEF
3// RUN: mlir-tblgen -print-records -I %S/../../include %s | FileCheck %s --check-prefix=RECORD
4
5include "mlir/IR/AttrTypeBase.td"
6include "mlir/IR/EnumAttr.td"
7include "mlir/IR/OpBase.td"
8
9def Test_Dialect : Dialect {
10  let name = "test";
11  let cppNamespace = "foobar";
12  let usePropertiesForAttributes = 0;
13}
14class NS_Op<string mnemonic, list<Trait> traits> :
15    Op<Test_Dialect, mnemonic, traits>;
16
17def SomeAttr : Attr<CPred<"some-condition">, "some attribute kind"> {
18  let storageType = "some-attr-kind";
19  let returnType = "some-return-type";
20  let convertFromStorage = "$_self.some-convert-from-storage()";
21  let constBuilderCall = "some-const-builder-call($_builder, $0)";
22}
23
24def SomeAttrDef : AttrDef<Test_Dialect, "SomeAttr"> {
25  let attrName = "test.some_attr";
26}
27
28
29// Test required, optional, default-valued attributes
30// ---
31
32def AOp : NS_Op<"a_op", []> {
33  let arguments = (ins
34      SomeAttr:$aAttr,
35      DefaultValuedAttr<SomeAttr, "4.2">:$bAttr,
36      OptionalAttr<SomeAttr>:$cAttr,
37      DefaultValuedOptionalAttr<SomeAttr, "4.2">:$dAttr
38  );
39}
40
41// DECL-LABEL: AOp declarations
42
43// Test attribute name methods
44// ---
45
46// DECL:      static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames()
47// DECL-NEXT:   static ::llvm::StringRef attrNames[] =
48// DECL-SAME:     {::llvm::StringRef("aAttr"), ::llvm::StringRef("bAttr"), ::llvm::StringRef("cAttr"), ::llvm::StringRef("dAttr")};
49// DECL-NEXT:   return ::llvm::ArrayRef(attrNames);
50
51// DECL:      ::mlir::StringAttr getAAttrAttrName()
52// DECL-NEXT:      return getAttributeNameForIndex(0);
53// DECL:      ::mlir::StringAttr getAAttrAttrName(::mlir::OperationName name)
54// DECL-NEXT:      return getAttributeNameForIndex(name, 0);
55
56// DECL:      ::mlir::StringAttr getBAttrAttrName()
57// DECL-NEXT:      return getAttributeNameForIndex(1);
58// DECL:      ::mlir::StringAttr getBAttrAttrName(::mlir::OperationName name)
59// DECL-NEXT:      return getAttributeNameForIndex(name, 1);
60
61// DECL:      ::mlir::StringAttr getCAttrAttrName()
62// DECL-NEXT:      return getAttributeNameForIndex(2);
63// DECL:      ::mlir::StringAttr getCAttrAttrName(::mlir::OperationName name)
64// DECL-NEXT:      return getAttributeNameForIndex(name, 2);
65
66// DEF-LABEL: AOp definitions
67
68// Test verify method
69// ---
70
71// DEF:      ::llvm::LogicalResult AOpAdaptor::verify
72// DEF:      ::mlir::Attribute tblgen_aAttr;
73// DEF: while (true) {
74// DEF-NEXT:   if (namedAttrIt == namedAttrRange.end())
75// DEF-NEXT:     return emitError(loc, "'test.a_op' op ""requires attribute 'aAttr'");
76// DEF-NEXT:   if (namedAttrIt->getName() == AOp::getAAttrAttrName(*odsOpName)) {
77// DEF-NEXT:     tblgen_aAttr = namedAttrIt->getValue();
78// DEF-NEXT:     break;
79// DEF:      ::mlir::Attribute tblgen_bAttr;
80// DEF-NEXT: ::mlir::Attribute tblgen_cAttr;
81// DEF-NEXT: ::mlir::Attribute tblgen_dAttr;
82// DEF-NEXT: while (true) {
83// DEF-NEXT:   if (namedAttrIt == namedAttrRange.end())
84// DEF-NEXT:     break;
85// DEF:        if (namedAttrIt->getName() == AOp::getBAttrAttrName(*odsOpName))
86// DEF-NEXT:     tblgen_bAttr = namedAttrIt->getValue();
87// DEF:        if (namedAttrIt->getName() == AOp::getCAttrAttrName(*odsOpName))
88// DEF-NEXT:     tblgen_cAttr = namedAttrIt->getValue();
89// DEF:      if (tblgen_aAttr && !((some-condition)))
90// DEF-NEXT:   return emitError(loc, "'test.a_op' op ""attribute 'aAttr' failed to satisfy constraint: some attribute kind");
91// DEF:      if (tblgen_bAttr && !((some-condition)))
92// DEF-NEXT:   return emitError(loc, "'test.a_op' op ""attribute 'bAttr' failed to satisfy constraint: some attribute kind");
93// DEF:      if (tblgen_cAttr && !((some-condition)))
94// DEF-NEXT:   return emitError(loc, "'test.a_op' op ""attribute 'cAttr' failed to satisfy constraint: some attribute kind");
95// DEF:      if (tblgen_dAttr && !((some-condition)))
96// DEF-NEXT:   return emitError(loc, "'test.a_op' op ""attribute 'dAttr' failed to satisfy constraint: some attribute kind");
97
98// Test getter methods
99// ---
100
101// DECL:      some-attr-kind getAAttrAttr()
102// DECL-NEXT:   ::llvm::cast<some-attr-kind>(::mlir::impl::getAttrFromSortedRange((*this)->getAttrs().begin() + 0, (*this)->getAttrs().end() - 0, getAAttrAttrName()))
103// DEF:      some-return-type AOp::getAAttr() {
104// DEF-NEXT:   auto attr = getAAttrAttr()
105// DEF-NEXT:   return attr.some-convert-from-storage();
106
107// DECL:      some-attr-kind getBAttrAttr()
108// DECL-NEXT:   ::llvm::dyn_cast_or_null<some-attr-kind>(::mlir::impl::getAttrFromSortedRange((*this)->getAttrs().begin() + 1, (*this)->getAttrs().end() - 0, getBAttrAttrName()))
109// DEF:      some-return-type AOp::getBAttr() {
110// DEF-NEXT:   auto attr = getBAttrAttr();
111// DEF-NEXT:   return attr.some-convert-from-storage();
112
113// DECL:      some-attr-kind getCAttrAttr()
114// DECL-NEXT:   ::llvm::dyn_cast_or_null<some-attr-kind>(::mlir::impl::getAttrFromSortedRange((*this)->getAttrs().begin() + 1, (*this)->getAttrs().end() - 0, getCAttrAttrName()))
115// DEF:      ::std::optional<some-return-type> AOp::getCAttr() {
116// DEF-NEXT:   auto attr = getCAttrAttr()
117// DEF-NEXT:   return attr ? ::std::optional<some-return-type>(attr.some-convert-from-storage()) : (::std::nullopt);
118
119// DECL:      some-attr-kind getDAttrAttr()
120// DECL-NEXT:   ::llvm::dyn_cast_or_null<some-attr-kind>(::mlir::impl::getAttrFromSortedRange((*this)->getAttrs().begin() + 1, (*this)->getAttrs().end() - 0, getDAttrAttrName()))
121// DEF:      some-return-type AOp::getDAttr() {
122// DEF-NEXT:   auto attr = getDAttrAttr();
123// DEF-NEXT:   if (!attr)
124// DEF-NEXT:       return some-const-builder-call(::mlir::Builder((*this)->getContext()), 4.2).some-convert-from-storage();
125// DEF-NEXT:   return attr.some-convert-from-storage();
126
127// Test setter methods
128// ---
129
130// DECL:      void setAAttrAttr(some-attr-kind attr) {
131// DECL-NEXT:   (*this)->setAttr(getAAttrAttrName(), attr);
132// DEF:      void AOp::setAAttr(some-return-type attrValue) {
133// DEF-NEXT:   (*this)->setAttr(getAAttrAttrName(), some-const-builder-call(::mlir::Builder((*this)->getContext()), attrValue));
134// DECL:      void setBAttrAttr(some-attr-kind attr) {
135// DECL-NEXT:   (*this)->setAttr(getBAttrAttrName(), attr);
136// DEF:      void AOp::setBAttr(some-return-type attrValue) {
137// DEF-NEXT:   (*this)->setAttr(getBAttrAttrName(), some-const-builder-call(::mlir::Builder((*this)->getContext()), attrValue));
138// DECL:      void setCAttrAttr(some-attr-kind attr) {
139// DECL-NEXT:   (*this)->setAttr(getCAttrAttrName(), attr);
140// DEF:      void AOp::setCAttr(::std::optional<some-return-type> attrValue) {
141// DEF-NEXT:   if (attrValue)
142// DEF-NEXT:     return (*this)->setAttr(getCAttrAttrName(), some-const-builder-call(::mlir::Builder((*this)->getContext()), *attrValue));
143// DEF-NEXT:   (*this)->removeAttr(getCAttrAttrName());
144
145// Test remove methods
146// ---
147
148// DECL: ::mlir::Attribute removeCAttrAttr() {
149// DECL-NEXT: return (*this)->removeAttr(getCAttrAttrName());
150
151// Test build methods
152// ---
153
154// DEF:      void AOp::build(
155// DEF:        odsState.addAttribute(getAAttrAttrName(odsState.name), aAttr);
156// DEF:        odsState.addAttribute(getBAttrAttrName(odsState.name), bAttr);
157// DEF:        if (cAttr) {
158// DEF-NEXT:     odsState.addAttribute(getCAttrAttrName(odsState.name), cAttr);
159
160// DEF:        odsState.addAttribute(getAAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, aAttr));
161// DEF-NEXT:   odsState.addAttribute(getBAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, bAttr));
162// DEF-NEXT:   if (cAttr) {
163// DEF-NEXT:   odsState.addAttribute(getCAttrAttrName(odsState.name), cAttr);
164// DEF-NEXT:   }
165// DEF-NOT:    if (dAttr)
166// DEF:        odsState.addAttribute(getDAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, dAttr));
167
168// DEF:      void AOp::build(
169// DEF:        some-return-type aAttr, some-return-type bAttr, /*optional*/some-attr-kind cAttr
170// DEF:        odsState.addAttribute(getAAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, aAttr));
171
172// DEF:      void AOp::build(
173// DEF:        ::llvm::ArrayRef<::mlir::NamedAttribute> attributes
174// DEF:      odsState.addAttributes(attributes);
175
176// DEF:      void AOp::populateDefaultAttrs
177
178// Test the above but with prefix.
179
180def Test2_Dialect : Dialect {
181  let name = "test2";
182  let cppNamespace = "foobar2";
183  let usePropertiesForAttributes = 0;
184}
185def AgetOp : Op<Test2_Dialect, "a_get_op", []> {
186  let arguments = (ins
187      SomeAttr:$aAttr,
188      DefaultValuedOptionalAttr<SomeAttr, "4.2">:$bAttr,
189      OptionalAttr<SomeAttr>:$cAttr
190  );
191}
192
193// DECL-LABEL: AgetOp declarations
194
195// Test attribute name methods
196// ---
197
198// DECL:      static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames()
199// DECL-NEXT:   static ::llvm::StringRef attrNames[] =
200// DECL-SAME:     {::llvm::StringRef("aAttr"), ::llvm::StringRef("bAttr"), ::llvm::StringRef("cAttr")};
201// DECL-NEXT:   return ::llvm::ArrayRef(attrNames);
202
203// DECL:      ::mlir::StringAttr getAAttrAttrName()
204// DECL-NEXT:      return getAttributeNameForIndex(0);
205// DECL:      ::mlir::StringAttr getAAttrAttrName(::mlir::OperationName name)
206// DECL-NEXT:      return getAttributeNameForIndex(name, 0);
207
208// DECL:      ::mlir::StringAttr getBAttrAttrName()
209// DECL-NEXT:      return getAttributeNameForIndex(1);
210// DECL:      ::mlir::StringAttr getBAttrAttrName(::mlir::OperationName name)
211// DECL-NEXT:      return getAttributeNameForIndex(name, 1);
212
213// DECL:      ::mlir::StringAttr getCAttrAttrName()
214// DECL-NEXT:      return getAttributeNameForIndex(2);
215// DECL:      ::mlir::StringAttr getCAttrAttrName(::mlir::OperationName name)
216// DECL-NEXT:      return getAttributeNameForIndex(name, 2);
217
218// DEF-LABEL: AgetOp definitions
219
220// Test verify method
221// ---
222
223// DEF:      ::llvm::LogicalResult AgetOpAdaptor::verify
224// DEF:      ::mlir::Attribute tblgen_aAttr;
225// DEF: while (true)
226// DEF:      ::mlir::Attribute tblgen_bAttr;
227// DEF-NEXT: ::mlir::Attribute tblgen_cAttr;
228// DEF: while (true)
229// DEF:      if (tblgen_aAttr && !((some-condition)))
230// DEF-NEXT:   return emitError(loc, "'test2.a_get_op' op ""attribute 'aAttr' failed to satisfy constraint: some attribute kind");
231// DEF:      if (tblgen_bAttr && !((some-condition)))
232// DEF-NEXT:   return emitError(loc, "'test2.a_get_op' op ""attribute 'bAttr' failed to satisfy constraint: some attribute kind");
233// DEF:      if (tblgen_cAttr && !((some-condition)))
234// DEF-NEXT:   return emitError(loc, "'test2.a_get_op' op ""attribute 'cAttr' failed to satisfy constraint: some attribute kind");
235
236// Test getter methods
237// ---
238
239// DECL:      some-attr-kind getAAttrAttr()
240// DECL-NEXT:   ::llvm::cast<some-attr-kind>(::mlir::impl::getAttrFromSortedRange({{.*}}))
241// DEF:      some-return-type AgetOp::getAAttr() {
242// DEF-NEXT:   auto attr = getAAttrAttr()
243// DEF-NEXT:   return attr.some-convert-from-storage();
244
245// DECL:      some-attr-kind getBAttrAttr()
246// DECL-NEXT:   return ::llvm::dyn_cast_or_null<some-attr-kind>(::mlir::impl::getAttrFromSortedRange({{.*}}))
247// DEF:      some-return-type AgetOp::getBAttr() {
248// DEF-NEXT:   auto attr = getBAttrAttr();
249// DEF-NEXT:   if (!attr)
250// DEF-NEXT:       return some-const-builder-call(::mlir::Builder((*this)->getContext()), 4.2).some-convert-from-storage();
251// DEF-NEXT:   return attr.some-convert-from-storage();
252
253// DECL:      some-attr-kind getCAttrAttr()
254// DECL-NEXT:   return ::llvm::dyn_cast_or_null<some-attr-kind>(::mlir::impl::getAttrFromSortedRange({{.*}}))
255// DEF:      ::std::optional<some-return-type> AgetOp::getCAttr() {
256// DEF-NEXT:   auto attr = getCAttrAttr()
257// DEF-NEXT:   return attr ? ::std::optional<some-return-type>(attr.some-convert-from-storage()) : (::std::nullopt);
258
259// Test setter methods
260// ---
261
262// DECL:      void setAAttrAttr(some-attr-kind attr) {
263// DECL-NEXT:   (*this)->setAttr(getAAttrAttrName(), attr);
264// DECL:      void setBAttrAttr(some-attr-kind attr) {
265// DECL-NEXT:   (*this)->setAttr(getBAttrAttrName(), attr);
266// DECL:      void setCAttrAttr(some-attr-kind attr) {
267// DECL-NEXT:   (*this)->setAttr(getCAttrAttrName(), attr);
268
269// Test remove methods
270// ---
271
272// DECL: ::mlir::Attribute removeCAttrAttr() {
273// DECL-NEXT: return (*this)->removeAttr(getCAttrAttrName());
274
275// Test build methods
276// ---
277
278// DEF:      void AgetOp::build(
279// DEF:        odsState.addAttribute(getAAttrAttrName(odsState.name), aAttr);
280// DEF:        odsState.addAttribute(getBAttrAttrName(odsState.name), bAttr);
281// DEF:        if (cAttr) {
282// DEF-NEXT:     odsState.addAttribute(getCAttrAttrName(odsState.name), cAttr);
283
284// DEF:      void AgetOp::build(
285// DEF:        some-return-type aAttr, /*optional*/some-return-type bAttr, /*optional*/some-attr-kind cAttr
286// DEF:        odsState.addAttribute(getAAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, aAttr));
287
288// DEF:      void AgetOp::build(
289// DEF:        ::llvm::ArrayRef<::mlir::NamedAttribute> attributes
290// DEF:      odsState.addAttributes(attributes);
291
292// Test the above but using properties.
293def ApropOp : NS_Op<"a_prop_op", []> {
294  let arguments = (ins
295      Property<"unsigned">:$aAttr,
296      DefaultValuedAttr<SomeAttr, "4.2">:$bAttr
297  );
298}
299
300// DEF-LABEL: ApropOp definitions
301// DEF:       void ApropOp::populateDefaultProperties
302
303def SomeTypeAttr : TypeAttrBase<"SomeType", "some type attribute">;
304
305def BOp : NS_Op<"b_op", []> {
306  let arguments = (ins
307    AnyAttr:$any_attr,
308    BoolAttr:$bool_attr,
309    I32Attr:$i32_attr,
310    I64Attr:$i64_attr,
311    F32Attr:$f32_attr,
312    F64Attr:$f64_attr,
313    StrAttr:$str_attr,
314    ElementsAttr:$elements_attr,
315    FlatSymbolRefAttr:$function_attr,
316    SomeTypeAttr:$some_type_attr,
317    ArrayAttr:$array_attr,
318    TypedArrayAttrBase<SomeAttr, "SomeAttr array">:$some_attr_array,
319    TypeAttr:$type_attr
320  );
321}
322
323
324// Test common attribute kinds' constraints
325// ---
326
327// DEF-LABEL: BOpAdaptor::verify
328// DEF: if (tblgen_any_attr && !((true)))
329// DEF: if (tblgen_bool_attr && !((::llvm::isa<::mlir::BoolAttr>(tblgen_bool_attr))))
330// DEF: if (tblgen_i32_attr && !(((::llvm::isa<::mlir::IntegerAttr>(tblgen_i32_attr))) && ((::llvm::cast<::mlir::IntegerAttr>(tblgen_i32_attr).getType().isSignlessInteger(32)))))
331// DEF: if (tblgen_i64_attr && !(((::llvm::isa<::mlir::IntegerAttr>(tblgen_i64_attr))) && ((::llvm::cast<::mlir::IntegerAttr>(tblgen_i64_attr).getType().isSignlessInteger(64)))))
332// DEF: if (tblgen_f32_attr && !(((::llvm::isa<::mlir::FloatAttr>(tblgen_f32_attr))) && ((::llvm::cast<::mlir::FloatAttr>(tblgen_f32_attr).getType().isF32()))))
333// DEF: if (tblgen_f64_attr && !(((::llvm::isa<::mlir::FloatAttr>(tblgen_f64_attr))) && ((::llvm::cast<::mlir::FloatAttr>(tblgen_f64_attr).getType().isF64()))))
334// DEF: if (tblgen_str_attr && !((::llvm::isa<::mlir::StringAttr>(tblgen_str_attr))))
335// DEF: if (tblgen_elements_attr && !((::llvm::isa<::mlir::ElementsAttr>(tblgen_elements_attr))))
336// DEF: if (tblgen_function_attr && !((::llvm::isa<::mlir::FlatSymbolRefAttr>(tblgen_function_attr))))
337// DEF: if (tblgen_some_type_attr && !(((::llvm::isa<::mlir::TypeAttr>(tblgen_some_type_attr))) && ((::llvm::isa<SomeType>(::llvm::cast<::mlir::TypeAttr>(tblgen_some_type_attr).getValue()))) && ((true))))
338// DEF: if (tblgen_array_attr && !((::llvm::isa<::mlir::ArrayAttr>(tblgen_array_attr))))
339// DEF: if (tblgen_some_attr_array && !(((::llvm::isa<::mlir::ArrayAttr>(tblgen_some_attr_array))) && (::llvm::all_of(::llvm::cast<::mlir::ArrayAttr>(tblgen_some_attr_array), [&](::mlir::Attribute attr) { return attr && ((some-condition)); }))))
340// DEF: if (tblgen_type_attr && !(((::llvm::isa<::mlir::TypeAttr>(tblgen_type_attr))) && ((::llvm::isa<::mlir::Type>(::llvm::cast<::mlir::TypeAttr>(tblgen_type_attr).getValue()))) && ((true))))
341
342// Test common attribute kind getters' return types
343// ---
344
345// DEF: ::mlir::Attribute BOp::getAnyAttr()
346// DEF: bool BOp::getBoolAttr()
347// DEF: uint32_t BOp::getI32Attr()
348// DEF: uint64_t BOp::getI64Attr()
349// DEF: ::llvm::APFloat BOp::getF32Attr()
350// DEF: ::llvm::APFloat BOp::getF64Attr()
351// DEF: ::llvm::StringRef BOp::getStrAttr()
352// DEF: ::mlir::ElementsAttr BOp::getElementsAttr()
353// DEF: ::llvm::StringRef BOp::getFunctionAttr()
354// DEF: SomeType BOp::getSomeTypeAttr()
355// DEF: ::mlir::ArrayAttr BOp::getArrayAttr()
356// DEF: ::mlir::ArrayAttr BOp::getSomeAttrArray()
357// DEF: ::mlir::Type BOp::getTypeAttr()
358
359// Test building constant values for array attribute kinds
360// ---
361
362def COp : NS_Op<"c_op", []> {
363  let arguments = (ins
364    DefaultValuedOptionalAttr<I32ArrayAttr, "{1, 2}">:$i32_array_attr,
365    DefaultValuedOptionalAttr<I64ArrayAttr, "{3, 4}">:$i64_array_attr,
366    DefaultValuedOptionalAttr<F32ArrayAttr, "{5.f, 6.f}">:$f32_array_attr,
367    DefaultValuedOptionalAttr<F64ArrayAttr, "{7., 8.}">:$f64_array_attr,
368    DefaultValuedOptionalAttr<StrArrayAttr, "{\"a\", \"b\"}">:$str_array_attr
369  );
370}
371
372// DEF-LABEL: COp definitions
373// DEF: ::mlir::Builder((*this)->getContext()).getI32ArrayAttr({1, 2})
374// DEF: ::mlir::Builder((*this)->getContext()).getI64ArrayAttr({3, 4})
375// DEF: ::mlir::Builder((*this)->getContext()).getF32ArrayAttr({5.f, 6.f})
376// DEF: ::mlir::Builder((*this)->getContext()).getF64ArrayAttr({7., 8.})
377// DEF: ::mlir::Builder((*this)->getContext()).getStrArrayAttr({"a", "b"})
378
379
380// Test builder method which takes unwrapped values for attributes
381// ---
382
383def I32Case5:  I32EnumAttrCase<"case5", 5>;
384def I32Case10: I32EnumAttrCase<"case10", 10>;
385
386def SomeI32Enum: I32EnumAttr<
387  "SomeI32Enum", "", [I32Case5, I32Case10]>;
388
389def DOp : NS_Op<"d_op", []> {
390  let arguments = (ins
391    I32Attr:$i32_attr,
392    F64Attr:$f64_attr,
393    StrAttr:$str_attr,
394    BoolAttr:$bool_attr,
395    SomeI32Enum:$enum_attr,
396    DefaultValuedAttr<I32Attr, "42">:$dv_i32_attr,
397    DefaultValuedAttr<F64Attr, "8.">:$dv_f64_attr,
398    DefaultValuedStrAttr<StrAttr, "abc">:$dv_str_attr,
399    DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr,
400    DefaultValuedAttr<SomeI32Enum, "::SomeI32Enum::case5">:$dv_enum_attr
401  );
402}
403
404// DECL-LABEL: DOp declarations
405// DECL: static void build({{.*}}, uint32_t i32_attr, ::llvm::APFloat f64_attr, ::llvm::StringRef str_attr, bool bool_attr, ::SomeI32Enum enum_attr, uint32_t dv_i32_attr, ::llvm::APFloat dv_f64_attr, ::llvm::StringRef dv_str_attr = "abc", bool dv_bool_attr = true, ::SomeI32Enum dv_enum_attr = ::SomeI32Enum::case5)
406
407// DEF-LABEL: DOp definitions
408// DEF: odsState.addAttribute(getStrAttrAttrName(odsState.name), odsBuilder.getStringAttr(str_attr));
409// DEF: odsState.addAttribute(getDvStrAttrAttrName(odsState.name), odsBuilder.getStringAttr(dv_str_attr));
410
411
412// Test default dictionary attribute.
413// ---
414
415def DefaultDictAttrOp : NS_Op<"default_dict_attr_op", []> {
416  let arguments = (ins
417    DefaultValuedAttr<DictionaryAttr, "{}">:$empty,
418    DefaultValuedAttr<DictionaryAttr, "getDefaultDictAttrs($_builder)">:$non_empty
419  );
420}
421
422// DEF-LABEL: DefaultDictAttrOp definitions
423// DEF: if (!attributes.get(attrNames[0]))
424// DEF:   attributes.append(attrNames[0], odsBuilder.getDictionaryAttr({}));
425// DEF: if (!attributes.get(attrNames[1]))
426// DEF:   attributes.append(attrNames[1], odsBuilder.getDictionaryAttr(getDefaultDictAttrs(odsBuilder)));
427
428// DECL-LABEL: DefaultDictAttrOp declarations
429// DECL: build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::DictionaryAttr empty = nullptr, ::mlir::DictionaryAttr non_empty = nullptr)
430
431
432// Test derived type attr.
433// ---
434def DerivedTypeAttrOp : NS_Op<"derived_type_attr_op", []> {
435  let results = (outs AnyTensor:$output);
436  DerivedTypeAttr element_dtype = DerivedTypeAttr<"return output().getType();">;
437}
438
439// DECL: class DerivedTypeAttrOp : public ::mlir::Op
440// DECL-SAME: DerivedAttributeOpInterface::Trait
441// DECL: static bool isDerivedAttribute
442// DEF: bool DerivedTypeAttrOp::isDerivedAttribute(::llvm::StringRef name) {
443// DEF:   if (name == "element_dtype") return true;
444// DEF:   return false;
445// DEF: }
446// DEF: DerivedTypeAttrOp::materializeDerivedAttributes
447
448// Test that only default valued attributes at the end of the arguments
449// list get default values in the builder signature
450// ---
451
452def EOp : NS_Op<"e_op", []> {
453  let arguments = (ins
454    I32Attr:$i32_attr,
455    DefaultValuedAttr<I32Attr, "42">:$dv_i32_attr,
456    F64Attr:$f64_attr,
457    DefaultValuedAttr<F64Attr, "8.">:$dv_f64_attr,
458    StrAttr:$str_attr,
459    DefaultValuedStrAttr<StrAttr, "abc">:$dv_str_attr,
460    BoolAttr:$bool_attr,
461    DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr,
462    SomeI32Enum:$enum_attr,
463    DefaultValuedAttr<SomeI32Enum, "::SomeI32Enum::case5">:$dv_enum_attr
464  );
465}
466
467// DECL-LABEL: EOp declarations
468// DECL: static void build({{.*}}, uint32_t i32_attr, uint32_t dv_i32_attr, ::llvm::APFloat f64_attr, ::llvm::APFloat dv_f64_attr, ::llvm::StringRef str_attr, ::llvm::StringRef dv_str_attr, bool bool_attr, bool dv_bool_attr, ::SomeI32Enum enum_attr, ::SomeI32Enum dv_enum_attr = ::SomeI32Enum::case5)
469
470
471// Test proper namespacing for AttrDef
472// ---
473
474def NamespaceOp : NS_Op<"namespace_op", []> {
475  let arguments = (ins
476      SomeAttrDef:$AttrDef
477  );
478}
479
480// Test mixing operands and attributes in arbitrary order
481// ---
482
483def MixOperandsAndAttrs : NS_Op<"mix_operands_and_attrs", []> {
484  let arguments = (ins F32Attr:$attr, F32:$operand, F32Attr:$otherAttr, F32:$otherArg);
485}
486
487// DECL-LABEL: MixOperandsAndAttrs declarations
488// DECL-DAG: ::mlir::TypedValue<::mlir::FloatType> getOperand()
489// DECL-DAG: ::mlir::TypedValue<::mlir::FloatType> getOtherArg()
490
491// DECL-LABEL: NamespaceOp declarations
492// DECL: foobar::SomeAttrAttr getAttrDef()
493
494
495def OpWithDefaultAndRegion : NS_Op<"default_with_region", []> {
496  let arguments = (ins
497          DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr
498  );
499  let regions = (region VariadicRegion<AnyRegion>:$region);
500}
501
502// We should not have a default attribute in this case.
503
504// DECL-LABEL: OpWithDefaultAndRegion declarations
505// DECL: static void build({{.*}}, bool dv_bool_attr, unsigned regionCount)
506
507def OpWithDefaultAndSuccessor : NS_Op<"default_with_succ", []> {
508  let arguments = (ins
509          DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr
510  );
511  let successors = (successor VariadicSuccessor<AnySuccessor>:$succ);
512}
513
514// We should not have a default attribute in this case.
515
516// DECL-LABEL: OpWithDefaultAndSuccessor declarations
517// DECL-DAG: static void build({{.*}}, bool dv_bool_attr, ::mlir::BlockRange succ)
518
519// DEF-LABEL: MixOperandsAndAttrs definitions
520// DEF-DAG: void MixOperandsAndAttrs::build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::FloatAttr attr, ::mlir::Value operand, ::mlir::FloatAttr otherAttr, ::mlir::Value otherArg)
521// DEF-DAG: ::llvm::APFloat MixOperandsAndAttrs::getAttr()
522// DEF-DAG: ::llvm::APFloat MixOperandsAndAttrs::getOtherAttr()
523
524// Test unit attributes.
525// ---
526
527def UnitAttrOp : NS_Op<"unit_attr_op", []> {
528  let arguments = (ins UnitAttr:$attr);
529}
530
531// DEF-LABEL: UnitAttrOp definitions
532// DEF: bool UnitAttrOp::getAttr() {
533// DEF:   return {{.*}} != nullptr
534
535
536// DEF: build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, /*optional*/::mlir::UnitAttr attr)
537// DEF: build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, /*optional*/bool attr)
538
539// DECL-LABEL: UnitAttrOp declarations
540// DECL: ::mlir::Attribute removeAttrAttr() {
541// DECL-NEXT:   (*this)->removeAttr(getAttrAttrName());
542// DECL: build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, /*optional*/bool attr = false)
543
544
545// Test elementAttr field of TypedArrayAttr.
546// ---
547
548def SomeTypedArrayAttr : TypedArrayAttrBase<SomeAttr, "SomeAttr array">;
549
550// RECORD-LABEL: def SomeTypedArrayAttr
551// RECORD: Attr elementAttr = SomeAttr;
552