Skip to content

Commit

Permalink
[mlir][DeclarativeParser] Emit an error if a : follows an attribute…
Browse files Browse the repository at this point in the history
… with a non-constant type.

Summary: The attribute grammar includes an optional trailing colon type, so for attributes without a constant buildable type this will generally lead to unexpected and undesired behavior. Given that, it's better to just error out on these cases.

Differential Revision: https://reviews.llvm.org/D77293
  • Loading branch information
River707 committed Apr 4, 2020
1 parent ca47ac3 commit e3bb363
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 56 deletions.
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/Affine/IR/AffineOpsBase.td
Expand Up @@ -20,6 +20,7 @@ def AffineMapAttr : Attr<
CPred<"$_self.isa<AffineMapAttr>()">, "AffineMap attribute"> {
let storageType = [{ AffineMapAttr }];
let returnType = [{ AffineMap }];
let valueType = Index;
let constBuilderCall = "AffineMapAttr::get($0)";
}

Expand Down
17 changes: 16 additions & 1 deletion mlir/include/mlir/IR/OpBase.td
Expand Up @@ -319,7 +319,8 @@ class BuildableType<code builder> {
def AnyType : Type<CPred<"true">, "any type">;

// None type
def NoneType : Type<CPred<"$_self.isa<NoneType>()">, "none type">;
def NoneType : Type<CPred<"$_self.isa<NoneType>()">, "none type">,
BuildableType<"$_builder.getType<NoneType>()">;

// Any type from the given list
class AnyTypeOf<list<Type> allowedTypes, string description = ""> : Type<
Expand Down Expand Up @@ -835,6 +836,7 @@ def AnyAttr : Attr<CPred<"true">, "any attribute"> {
def BoolAttr : Attr<CPred<"$_self.isa<BoolAttr>()">, "bool attribute"> {
let storageType = [{ BoolAttr }];
let returnType = [{ bool }];
let valueType = I1;
let constBuilderCall = "$_builder.getBoolAttr($0)";
}

Expand Down Expand Up @@ -942,11 +944,18 @@ class StringBasedAttr<Pred condition, string descr> : Attr<condition, descr> {
let constBuilderCall = "$_builder.getStringAttr(\"$0\")";
let storageType = [{ StringAttr }];
let returnType = [{ StringRef }];
let valueType = NoneType;
}

def StrAttr : StringBasedAttr<CPred<"$_self.isa<StringAttr>()">,
"string attribute">;

// String attribute that has a specific value type.
class TypedStrAttr<Type ty> : StringBasedAttr<CPred<"$_self.isa<StringAttr>()">,
"string attribute"> {
let valueType = ty;
}

// Base class for attributes containing types. Example:
// def IntTypeAttr : TypeAttrBase<"IntegerType", "integer type attribute">
// defines a type attribute containing an integer type.
Expand All @@ -957,6 +966,7 @@ class TypeAttrBase<string retType, string description> :
description> {
let storageType = [{ TypeAttr }];
let returnType = retType;
let valueType = NoneType;
let convertFromStorage = "$_self.getValue().cast<" # retType # ">()";
}

Expand All @@ -970,6 +980,7 @@ def UnitAttr : Attr<CPred<"$_self.isa<UnitAttr>()">, "unit attribute"> {
let constBuilderCall = "$_builder.getUnitAttr()";
let convertFromStorage = "$_self != nullptr";
let returnType = "bool";
let valueType = NoneType;
let isOptional = 1;
}

Expand Down Expand Up @@ -1166,6 +1177,7 @@ class DictionaryAttrBase : Attr<CPred<"$_self.isa<DictionaryAttr>()">,
"dictionary of named attribute values"> {
let storageType = [{ DictionaryAttr }];
let returnType = [{ DictionaryAttr }];
let valueType = NoneType;
let convertFromStorage = "$_self";
}

Expand Down Expand Up @@ -1285,6 +1297,7 @@ class ArrayAttrBase<Pred condition, string description> :
Attr<condition, description> {
let storageType = [{ ArrayAttr }];
let returnType = [{ ArrayAttr }];
let valueType = NoneType;
let convertFromStorage = "$_self";
}

Expand Down Expand Up @@ -1364,13 +1377,15 @@ def SymbolRefAttr : Attr<CPred<"$_self.isa<SymbolRefAttr>()">,
"symbol reference attribute"> {
let storageType = [{ SymbolRefAttr }];
let returnType = [{ SymbolRefAttr }];
let valueType = NoneType;
let constBuilderCall = "$_builder.getSymbolRefAttr($0)";
let convertFromStorage = "$_self";
}
def FlatSymbolRefAttr : Attr<CPred<"$_self.isa<FlatSymbolRefAttr>()">,
"flat symbol reference attribute"> {
let storageType = [{ FlatSymbolRefAttr }];
let returnType = [{ StringRef }];
let valueType = NoneType;
let constBuilderCall = "$_builder.getSymbolRefAttr($0)";
let convertFromStorage = "$_self.getValue()";
}
Expand Down
2 changes: 1 addition & 1 deletion mlir/test/IR/attribute.mlir
Expand Up @@ -247,7 +247,7 @@ func @non_type_in_type_array_attr_fail() {
// CHECK-LABEL: func @string_attr_custom_type
func @string_attr_custom_type() {
// CHECK: "string_data" : !foo.string
test.string_attr_with_type "string_data"
test.string_attr_with_type "string_data" : !foo.string
return
}

Expand Down
11 changes: 2 additions & 9 deletions mlir/test/lib/Dialect/Test/TestOps.td
Expand Up @@ -158,15 +158,8 @@ def TypeArrayAttrOp : TEST_Op<"type_array_attr"> {
let arguments = (ins TypeArrayAttr:$attr);
}
def TypeStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> {
let arguments = (ins StrAttr:$attr);
let printer = [{ p << getAttr("attr"); }];
let parser = [{
Attribute attr;
Type stringType = OpaqueType::get(Identifier::get("foo",
result.getContext()), "string",
result.getContext());
return parser.parseAttribute(attr, stringType, "attr", result.attributes);
}];
let arguments = (ins TypedStrAttr<AnyType>:$attr);
let assemblyFormat = "$attr attr-dict";
}

def StrCaseA: StrEnumAttrCase<"A">;
Expand Down
17 changes: 16 additions & 1 deletion mlir/test/mlir-tblgen/op-format-spec.td
@@ -1,4 +1,4 @@
// RUN: mlir-tblgen -gen-op-decls -asmformat-error-is-fatal=false -I %S/../../include %s 2>&1 | FileCheck %s --dump-input-on-failure
// RUN: mlir-tblgen -gen-op-decls -asmformat-error-is-fatal=false -I %S/../../include %s -o=%t 2>&1 | FileCheck %s --dump-input-on-failure

// This file contains tests for the specification of the declarative op format.

Expand Down Expand Up @@ -275,6 +275,21 @@ def VariableInvalidG : TestFormat_Op<"variable_invalid_g", [{
}]> {
let successors = (successor AnySuccessor:$successor);
}
// CHECK: error: format ambiguity caused by `:` literal found after attribute `attr` which does not have a buildable type
def VariableInvalidH : TestFormat_Op<"variable_invalid_h", [{
$attr `:` attr-dict
}]>, Arguments<(ins ElementsAttr:$attr)>;
// CHECK: error: format ambiguity caused by `:` literal found after attribute `attr` which does not have a buildable type
def VariableInvalidI : TestFormat_Op<"variable_invalid_i", [{
(`foo` $attr^)? `:` attr-dict
}]>, Arguments<(ins OptionalAttr<ElementsAttr>:$attr)>;
// CHECK-NOT: error:
def VariableInvalidJ : TestFormat_Op<"variable_invalid_j", [{
$attr `:` attr-dict
}]>, Arguments<(ins OptionalAttr<I1Attr>:$attr)>;
def VariableInvalidK : TestFormat_Op<"variable_invalid_k", [{
(`foo` $attr^)? `:` attr-dict
}]>, Arguments<(ins OptionalAttr<I1Attr>:$attr)>;

//===----------------------------------------------------------------------===//
// Coverage Checks
Expand Down

0 comments on commit e3bb363

Please sign in to comment.