Skip to content

Commit 44610c0

Browse files
committed
[MLIR][ODS] default-valued strings should be in quotes
`DefaultValuedAttr<StrAttr, "">` and `ConstantAttr<StrAttr, "">` result in bugs in which TableGen will not recognize that the attribute has a default value, because `""` is an empty TableGen string. Strings no longer have special treatment. Instead, string values must be wrapped in quotes: "\"foo\"". Two helpers, `DefaultValuedStrAttr` and `ConstantStrAttr` have been added to keep code clean. Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D111855
1 parent 7dd7078 commit 44610c0

File tree

8 files changed

+69
-19
lines changed

8 files changed

+69
-19
lines changed

mlir/include/mlir/IR/OpBase.td

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,11 @@ class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.summary> {
928928
let baseAttr = attr;
929929
}
930930

931+
// Default-valued string-based attribute. Wraps the default value in escaped
932+
// quotes.
933+
class DefaultValuedStrAttr<Attr attr, string val>
934+
: DefaultValuedAttr<attr, "\"" # val # "\"">;
935+
931936
//===----------------------------------------------------------------------===//
932937
// Primitive attribute kinds
933938

@@ -1095,7 +1100,7 @@ def F64Attr : FloatAttrBase<F64, "64-bit float attribute">;
10951100

10961101
// An attribute backed by a string type.
10971102
class StringBasedAttr<Pred condition, string descr> : Attr<condition, descr> {
1098-
let constBuilderCall = "$_builder.getStringAttr(\"$0\")";
1103+
let constBuilderCall = "$_builder.getStringAttr($0)";
10991104
let storageType = [{ ::mlir::StringAttr }];
11001105
let returnType = [{ ::llvm::StringRef }];
11011106
let valueType = NoneType;
@@ -1672,6 +1677,10 @@ def ConstBoolAttrFalse : ConstantAttr<BoolAttr, "false">;
16721677
def ConstBoolAttrTrue : ConstantAttr<BoolAttr, "true">;
16731678
def ConstUnitAttr : ConstantAttr<UnitAttr, "unit">;
16741679

1680+
// Constant string-based attribute. Wraps the desired string in escaped quotes.
1681+
class ConstantStrAttr<Attr attribute, string val>
1682+
: ConstantAttr<attribute, "\"" # val # "\"">;
1683+
16751684
//===----------------------------------------------------------------------===//
16761685
// Common attribute constraints
16771686
//===----------------------------------------------------------------------===//

mlir/test/lib/Dialect/Test/TestOps.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,4 +2343,21 @@ def TestLinalgConvOp :
23432343
}];
23442344
}
23452345

2346+
//===----------------------------------------------------------------------===//
2347+
// Test Ops with Default-Valued String Attributes
2348+
//===----------------------------------------------------------------------===//
2349+
2350+
def TestDefaultStrAttrNoValueOp : TEST_Op<"no_str_value"> {
2351+
let arguments = (ins DefaultValuedAttr<StrAttr, "">:$value);
2352+
let assemblyFormat = "attr-dict";
2353+
}
2354+
2355+
def TestDefaultStrAttrHasValueOp : TEST_Op<"has_str_value"> {
2356+
let arguments = (ins DefaultValuedStrAttr<StrAttr, "">:$value);
2357+
let assemblyFormat = "attr-dict";
2358+
}
2359+
2360+
def : Pat<(TestDefaultStrAttrNoValueOp $value),
2361+
(TestDefaultStrAttrHasValueOp ConstantStrAttr<StrAttr, "foo">)>;
2362+
23462363
#endif // TEST_OPS
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// RUN: mlir-opt -verify-diagnostics %s
2+
3+
// Test DefaultValuedAttr<StrAttr, ""> is recognized as "no default value"
4+
test.no_str_value {} // expected-error {{'test.no_str_value' op requires attribute 'value'}}

mlir/test/mlir-tblgen/op-attribute.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def DOp : NS_Op<"d_op", []> {
337337
SomeI32Enum:$enum_attr,
338338
DefaultValuedAttr<I32Attr, "42">:$dv_i32_attr,
339339
DefaultValuedAttr<F64Attr, "8.">:$dv_f64_attr,
340-
DefaultValuedAttr<StrAttr, "abc">:$dv_str_attr,
340+
DefaultValuedStrAttr<StrAttr, "abc">:$dv_str_attr,
341341
DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr,
342342
DefaultValuedAttr<SomeI32Enum, "::SomeI32Enum::case5">:$dv_enum_attr
343343
);
@@ -377,7 +377,7 @@ def EOp : NS_Op<"e_op", []> {
377377
F64Attr:$f64_attr,
378378
DefaultValuedAttr<F64Attr, "8.">:$dv_f64_attr,
379379
StrAttr:$str_attr,
380-
DefaultValuedAttr<StrAttr, "abc">:$dv_str_attr,
380+
DefaultValuedStrAttr<StrAttr, "abc">:$dv_str_attr,
381381
BoolAttr:$bool_attr,
382382
DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr,
383383
SomeI32Enum:$enum_attr,

mlir/test/mlir-tblgen/op-format.mlir

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,10 @@ test.format_infer_variadic_type_from_non_variadic %i64, %i64 : i64
361361

362362
// CHECK: test.format_infer_type
363363
%ignored_res7 = test.format_infer_type
364+
365+
//===----------------------------------------------------------------------===//
366+
// Check DefaultValuedStrAttr
367+
//===----------------------------------------------------------------------===//
368+
369+
// CHECK: test.has_str_value
370+
test.has_str_value {}

mlir/test/mlir-tblgen/pattern.mlir

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,13 @@ func @returnTypeAndLocation(%arg0 : i32) -> i1 {
583583
// CHECK: "test.two_to_one"(%0, %1) : (i32, i32) -> i1
584584
return %0 : i1
585585
}
586+
587+
//===----------------------------------------------------------------------===//
588+
// Test that patterns can create ConstantStrAttr
589+
//===----------------------------------------------------------------------===//
590+
591+
func @testConstantStrAttr() -> () {
592+
// CHECK: test.has_str_value {value = "foo"}
593+
test.no_str_value {value = "bar"}
594+
return
595+
}

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,12 +1710,7 @@ void OpEmitter::buildParamList(SmallVectorImpl<OpMethodParameter> &paramList,
17101710
std::string defaultValue;
17111711
if (attrParamKind == AttrParamKind::UnwrappedValue &&
17121712
i >= defaultValuedAttrStartIndex) {
1713-
bool isString = attr.getReturnType() == "::llvm::StringRef";
1714-
if (isString)
1715-
defaultValue.append("\"");
17161713
defaultValue += attr.getDefaultValue();
1717-
if (isString)
1718-
defaultValue.append("\"");
17191714
}
17201715
paramList.emplace_back(type, namedAttr.name, defaultValue, properties);
17211716
}

mlir/tools/mlir-tblgen/RewriterGen.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ struct format_provider<mlir::tblgen::Pattern::IdentifierLine> {
5050
};
5151
} // end namespace llvm
5252

53+
static std::string escapeString(StringRef value) {
54+
std::string ret;
55+
llvm::raw_string_ostream os(ret);
56+
llvm::printEscapedString(value, os);
57+
return os.str();
58+
}
59+
5360
//===----------------------------------------------------------------------===//
5461
// PatternEmitter
5562
//===----------------------------------------------------------------------===//
@@ -189,7 +196,7 @@ class PatternEmitter {
189196

190197
// Returns the C++ expression to construct a constant attribute of the given
191198
// `value` for the given attribute kind `attr`.
192-
std::string handleConstantAttr(Attribute attr, StringRef value);
199+
std::string handleConstantAttr(Attribute attr, const Twine &value);
193200

194201
// Returns the C++ expression to build an argument from the given DAG `leaf`.
195202
// `patArgName` is used to bound the argument to the source pattern.
@@ -313,7 +320,7 @@ PatternEmitter::PatternEmitter(Record *pat, RecordOperatorMap *mapper,
313320
}
314321

315322
std::string PatternEmitter::handleConstantAttr(Attribute attr,
316-
StringRef value) {
323+
const Twine &value) {
317324
if (!attr.isConstBuildable())
318325
PrintFatalError(loc, "Attribute " + attr.getAttrDefName() +
319326
" does not have the 'constBuilderCall' field");
@@ -492,7 +499,8 @@ void PatternEmitter::emitNativeCodeMatch(DagNode tree, StringRef opName,
492499
formatv("\"operand {0} of native code call '{1}' failed to satisfy "
493500
"constraint: "
494501
"'{2}'\"",
495-
i, tree.getNativeCodeTemplate(), constraint.getSummary()));
502+
i, tree.getNativeCodeTemplate(),
503+
escapeString(constraint.getSummary())));
496504
}
497505

498506
LLVM_DEBUG(llvm::dbgs() << "done emitting match for native code call\n");
@@ -630,7 +638,7 @@ void PatternEmitter::emitOperandMatch(DagNode tree, StringRef opName,
630638
formatv("\"operand {0} of op '{1}' failed to satisfy constraint: "
631639
"'{2}'\"",
632640
operand - op.operand_begin(), op.getOperationName(),
633-
constraint.getSummary()));
641+
escapeString(constraint.getSummary())));
634642
}
635643
}
636644

@@ -694,9 +702,9 @@ void PatternEmitter::emitAttributeMatch(DagNode tree, StringRef opName,
694702
opName,
695703
tgfmt(matcher.getConditionTemplate(), &fmtCtx.withSelf("tblgen_attr")),
696704
formatv("\"op '{0}' attribute '{1}' failed to satisfy constraint: "
697-
"{2}\"",
705+
"'{2}'\"",
698706
op.getOperationName(), namedAttr->name,
699-
matcher.getAsConstraint().getSummary()));
707+
escapeString(matcher.getAsConstraint().getSummary())));
700708
}
701709

702710
// Capture the value
@@ -740,8 +748,8 @@ void PatternEmitter::emitMatchLogic(DagNode tree, StringRef opName) {
740748
symbolInfoMap.getValueAndRangeUse(entities.front()));
741749
emitMatchCheck(
742750
opName, tgfmt(condition, &fmtCtx.withSelf(self.str())),
743-
formatv("\"value entity '{0}' failed to satisfy constraint: {1}\"",
744-
entities.front(), constraint.getSummary()));
751+
formatv("\"value entity '{0}' failed to satisfy constraint: '{1}'\"",
752+
entities.front(), escapeString(constraint.getSummary())));
745753

746754
} else if (isa<AttrConstraint>(constraint)) {
747755
PrintFatalError(
@@ -765,9 +773,9 @@ void PatternEmitter::emitMatchLogic(DagNode tree, StringRef opName) {
765773
tgfmt(condition, &fmtCtx.withSelf(self), names[0],
766774
names[1], names[2], names[3]),
767775
formatv("\"entities '{0}' failed to satisfy constraint: "
768-
"{1}\"",
776+
"'{1}'\"",
769777
llvm::join(entities, ", "),
770-
constraint.getSummary()));
778+
escapeString(constraint.getSummary())));
771779
}
772780
}
773781

@@ -1103,7 +1111,7 @@ std::string PatternEmitter::handleOpArgument(DagLeaf leaf,
11031111
if (leaf.isEnumAttrCase()) {
11041112
auto enumCase = leaf.getAsEnumAttrCase();
11051113
if (enumCase.isStrCase())
1106-
return handleConstantAttr(enumCase, enumCase.getSymbol());
1114+
return handleConstantAttr(enumCase, "\"" + enumCase.getSymbol() + "\"");
11071115
// This is an enum case backed by an IntegerAttr. We need to get its value
11081116
// to build the constant.
11091117
std::string val = std::to_string(enumCase.getValue());

0 commit comments

Comments
 (0)