diff --git a/mlir/include/mlir/IR/AttrTypeBase.td b/mlir/include/mlir/IR/AttrTypeBase.td --- a/mlir/include/mlir/IR/AttrTypeBase.td +++ b/mlir/include/mlir/IR/AttrTypeBase.td @@ -401,4 +401,33 @@ "::mlir::NoneType::get($_ctxt)", typeBuilder); } +//===----------------------------------------------------------------------===// +// ArrayOfAttr +//===----------------------------------------------------------------------===// + +/// This class defines an attribute that contains an array of elements. The +/// elements can be any type, but if they are attributes, the nested elements +/// are parsed and printed using the custom attribute syntax. +class ArrayOfAttr traits = []> + : AttrDef { + let parameters = (ins ArrayRefParameter:$value); + let mnemonic = attrMnemonic; + let assemblyFormat = "`[` $value `]`"; + + let returnType = "::llvm::ArrayRef<" # eltName # ">"; + let constBuilderCall = "$_builder.getAttr<" # attrName # "Attr>($0)"; + let convertFromStorage = "$_self.getValue()"; + + let extraClassDeclaration = [{ + auto begin() const { return getValue().begin(); } + auto end() const { return getValue().end(); } + bool empty() const { return getValue().empty(); } + size_t size() const { return getValue().size(); } + auto &front() const { return getValue().front(); } + auto &back() const { return getValue().back(); } + auto &operator[](size_t index) { return getValue()[index]; } + }]; +} + #endif // ATTRTYPEBASE_TD diff --git a/mlir/test/IR/array-of-attr.mlir b/mlir/test/IR/array-of-attr.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/IR/array-of-attr.mlir @@ -0,0 +1,10 @@ +// RUN: mlir-opt %s | mlir-opt | FileCheck %s + +// CHECK: test.array_of_attr_op +test.array_of_attr_op + // CHECK-SAME: a = [ begin 0 : index end, begin 2 : index end ] + a = [begin 0 : index end, begin 2 : index end], + // CHECK-SAME: [0, 1, -42, 42] + b = [0, 1, -42, 42], + // CHECK-SAME: [a, b, b, a] + c = [a, b, b, a] diff --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td --- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td +++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td @@ -17,6 +17,7 @@ include "TestDialect.td" include "mlir/IR/AttrTypeBase.td" include "mlir/IR/BuiltinAttributeInterfaces.td" +include "mlir/IR/EnumAttr.td" include "mlir/IR/OpAsmInterface.td" include "mlir/IR/SubElementInterfaces.td" @@ -266,4 +267,28 @@ let assemblyFormat = "`<` $handle `>`"; } +// An array of nested attributes. +def TestArrayOfUglyAttrs : ArrayOfAttr { + let assemblyFormat = "`[` $value ` ` `]`"; +} + +// An array of integers. +def TestArrayOfInts : ArrayOfAttr; + +// An array of enum attributes. +def TestSimpleEnum : I32EnumAttr<"SimpleEnum", "", [ + I32EnumAttrCase<"a", 0>, + I32EnumAttrCase<"b", 1> + ]> { + let genSpecializedAttr = 0; + let cppNamespace = "::test"; +} +def TestSimpleEnumAttr : EnumAttr { + let assemblyFormat = "`` $value"; +} +def TestArrayOfEnums : ArrayOfAttr; + #endif // TEST_ATTRDEFS diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -2474,6 +2474,17 @@ }]; } +//===----------------------------------------------------------------------===// +// Test ArrayOfAttr +//===----------------------------------------------------------------------===// + +// Embed the array attributes directly in the assembly format for a nice syntax. +def ArrayOfAttrOp : TEST_Op<"array_of_attr_op"> { + let arguments = (ins TestArrayOfUglyAttrs:$a, TestArrayOfInts:$b, + TestArrayOfEnums:$c); + let assemblyFormat = "`a` `=` $a `,` `b` `=` $b `,` `c` `=` $c attr-dict"; +} + //===----------------------------------------------------------------------===// // Test SideEffects //===----------------------------------------------------------------------===//