diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -1188,15 +1188,16 @@ //===----------------------------------------------------------------------===// // Composite attribute kinds -class DictionaryAttrBase : Attr()">, - "dictionary of named attribute values"> { +class DictionaryAttrBase : + Attr { let storageType = [{ DictionaryAttr }]; let returnType = [{ DictionaryAttr }]; let valueType = NoneType; let convertFromStorage = "$_self"; } -def DictionaryAttr : DictionaryAttrBase; +def DictionaryAttr : DictionaryAttrBase()">, + "dictionary of named attribute values">; class ElementsAttrBase : Attr { @@ -1380,7 +1381,11 @@ // validation method and set of accessors for a fixed set of fields. This is // useful when representing data that would normally be in a structure. class StructAttr attributes> : DictionaryAttrBase { + list attributes> : + DictionaryAttrBase()">, + "DictionaryAttr with field(s): " # + StrJoin.result # + " (each field having its own constraints)"> { // Name for this StructAttr. string className = name; diff --git a/mlir/test/IR/attribute.mlir b/mlir/test/IR/attribute.mlir --- a/mlir/test/IR/attribute.mlir +++ b/mlir/test/IR/attribute.mlir @@ -537,3 +537,23 @@ return } +//===----------------------------------------------------------------------===// +// Test StructAttr +//===----------------------------------------------------------------------===// + +// ----- + +func @missing_fields() { + // expected-error @+1 {{failed to satisfy constraint: DictionaryAttr with field(s): 'some_field', 'some_other_field' (each field having its own constraints)}} + "test.struct_attr"() {the_struct_attr = {}} : () -> () + return +} + +// ----- + +func @erroneous_fields() { + // expected-error @+1 {{failed to satisfy constraint: DictionaryAttr with field(s): 'some_field', 'some_other_field' (each field having its own constraints)}} + "test.struct_attr"() {the_struct_attr = {some_field = 1 : i8, some_other_field = 1}} : () -> () + return +} + diff --git a/mlir/test/lib/Dialect/Test/CMakeLists.txt b/mlir/test/lib/Dialect/Test/CMakeLists.txt --- a/mlir/test/lib/Dialect/Test/CMakeLists.txt +++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt @@ -9,6 +9,8 @@ mlir_tablegen(TestOpsDialect.h.inc -gen-dialect-decls) mlir_tablegen(TestOpEnums.h.inc -gen-enum-decls) mlir_tablegen(TestOpEnums.cpp.inc -gen-enum-defs) +mlir_tablegen(TestOpStructs.h.inc -gen-struct-attr-decls) +mlir_tablegen(TestOpStructs.cpp.inc -gen-struct-attr-defs) mlir_tablegen(TestPatterns.inc -gen-rewriters) add_public_tablegen_target(MLIRTestOpsIncGen) diff --git a/mlir/test/lib/Dialect/Test/TestDialect.h b/mlir/test/lib/Dialect/Test/TestDialect.h --- a/mlir/test/lib/Dialect/Test/TestDialect.h +++ b/mlir/test/lib/Dialect/Test/TestDialect.h @@ -30,6 +30,7 @@ namespace mlir { +#include "TestOpStructs.h.inc" #include "TestOpsDialect.h.inc" #define GET_OP_CLASSES diff --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp --- a/mlir/test/lib/Dialect/Test/TestDialect.cpp +++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp @@ -480,6 +480,7 @@ static mlir::DialectRegistration testDialect; #include "TestOpEnums.cpp.inc" +#include "TestOpStructs.cpp.inc" #define GET_OP_CLASSES #include "TestOps.cpp.inc" 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 @@ -196,6 +196,15 @@ let results = (outs I32:$val); } +def SomeStructAttr : StructAttr<"SomeStructAttr", Test_Dialect, [ + StructFieldAttr<"some_field", I64Attr>, + StructFieldAttr<"some_other_field", I64Attr> +]> {} + +def StructAttrOp : TEST_Op<"struct_attr"> { + let arguments = (ins SomeStructAttr:$the_struct_attr); + let results = (outs); +} def IntAttrOp : TEST_Op<"int_attrs"> { let arguments = (ins