From 9c9f479a7dc10e16fd8032875a477827db4b3b77 Mon Sep 17 00:00:00 2001 From: Sean Silva Date: Mon, 27 Apr 2020 17:52:59 -0700 Subject: [PATCH] Make ops with StructAttr's actually verify `isa`. Previously, they would only only verify `isa` on such attrs which resulted in crashes down the line from code assuming that the verifier was doing the more thorough check introduced in this patch. The key change here is for StructAttr to use `CPred<"$_self.isa<" # name # ">()">` instead of `isa`. To test this, introduce struct attrs to the test dialect. Previously, StructAttr was only being tested by unittests/, which didn't verify how StructAttr interacted with ODS. Differential Revision: https://reviews.llvm.org/D78975 --- mlir/include/mlir/IR/OpBase.td | 13 +++++++++---- mlir/test/IR/attribute.mlir | 20 ++++++++++++++++++++ mlir/test/lib/Dialect/Test/CMakeLists.txt | 2 ++ mlir/test/lib/Dialect/Test/TestDialect.cpp | 1 + mlir/test/lib/Dialect/Test/TestDialect.h | 1 + mlir/test/lib/Dialect/Test/TestOps.td | 9 +++++++++ 6 files changed, 42 insertions(+), 4 deletions(-) diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td index 59be446..9e361ef 100644 --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -1188,15 +1188,16 @@ class BitEnumAttr()">, - "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 @@ class StructFieldAttr { // 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 index 2a43f8a..16f244d 100644 --- a/mlir/test/IR/attribute.mlir +++ b/mlir/test/IR/attribute.mlir @@ -537,3 +537,23 @@ func @wrong_shape_fail() { 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 index 5b97e11..ae62fb0 100644 --- a/mlir/test/lib/Dialect/Test/CMakeLists.txt +++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt @@ -9,6 +9,8 @@ mlir_tablegen(TestOps.cpp.inc -gen-op-defs) 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.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp index fa99d47..048db3a 100644 --- a/mlir/test/lib/Dialect/Test/TestDialect.cpp +++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp @@ -480,6 +480,7 @@ void StringAttrPrettyNameOp::getAsmResultNames( 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/TestDialect.h b/mlir/test/lib/Dialect/Test/TestDialect.h index b4ca125..ea386c0 100644 --- 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/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index 1da2e71..8fb290a 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -196,6 +196,15 @@ def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> { 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 -- 2.7.4